Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #15175 > unrolled thread

problem with template friend partial specialization

Started byAndrey Dj <djdron@gmail.com>
First post2012-04-02 02:35 -0700
Last post2012-04-05 07:09 -0700
Articles 4 — 3 participants

Back to article view | Back to comp.lang.c++


Contents

  problem with template friend partial specialization Andrey Dj <djdron@gmail.com> - 2012-04-02 02:35 -0700
    Re: problem with template friend partial specialization Victor Bazarov <v.bazarov@comcast.invalid> - 2012-04-03 08:52 -0400
      Re: problem with template friend partial specialization Kalle Olavi Niemitalo <kon@iki.fi> - 2012-04-04 01:15 +0300
        Re: problem with template friend partial specialization Andrey Dj <djdron@gmail.com> - 2012-04-05 07:09 -0700

#15175 — problem with template friend partial specialization

FromAndrey Dj <djdron@gmail.com>
Date2012-04-02 02:35 -0700
Subjectproblem with template friend partial specialization
Message-ID<13976142.1067.1333359344646.JavaMail.geo-discussion-forums@ynel5>
Hello!

I found some interesting case of non-compiling C++ code.
Look at first example:

--------------------------------
template<class T> void Foo(T*);
class Bar;
template<> void Foo(Bar*);

class Bar
{
    friend void ::Foo<>(Bar*);
};
--------------------------------

Compiling... All fine.

Now add to Foo return type of Baz:

--------------------------------
class Baz {};

template<class T> Baz Foo(T*);
class Bar;
template<> Baz Foo(Bar*);

class Bar
{
    friend Baz ::Foo<>(Bar*);
};
--------------------------------

Trying to compile:
MSVC: error C2039: 'Foo' : is not a member of 'Baz'
GCC: error: 'Foo' in class 'Baz' does not name a type

Is there any way to declare such friend partial specialization?

[toc] | [next] | [standalone]


#15199

FromVictor Bazarov <v.bazarov@comcast.invalid>
Date2012-04-03 08:52 -0400
Message-ID<jlerpn$ctc$1@dont-email.me>
In reply to#15175
On 4/2/2012 5:35 AM, Andrey Dj wrote:
> Hello!
>
> I found some interesting case of non-compiling C++ code.
> Look at first example:
>
> --------------------------------
> template<class T>  void Foo(T*);
> class Bar;
> template<>  void Foo(Bar*);
>
> class Bar
> {
>      friend void ::Foo<>(Bar*);
> };
> --------------------------------
>
> Compiling... All fine.
>
> Now add to Foo return type of Baz:
>
> --------------------------------
> class Baz {};
>
> template<class T>  Baz Foo(T*);
> class Bar;
> template<>  Baz Foo(Bar*);
>
> class Bar
> {
>      friend Baz ::Foo<>(Bar*);
> };
> --------------------------------
>
> Trying to compile:
> MSVC: error C2039: 'Foo' : is not a member of 'Baz'
> GCC: error: 'Foo' in class 'Baz' does not name a type
>
> Is there any way to declare such friend partial specialization?

It's a tokenization problem, obviously.  Your compiler treats the colons 
before 'Foo' in the friend declaration as part of an elaborate name 
specifier that starts with 'Baz'.  It knows that 'Baz' is a class name...

You could try adding a 'using' declaration before the 'friend':

     class Bar
     {
        using ::Foo;
        friend Baz Foo<>(Bar*);
     };

(I've not tried it).  Or you could put 'Baz' in parentheses:

     class Bar
     {
        friend (Baz) ::Foo<>(Bar*);
     };

(I've not tried it either).  What you essentially need is tell the 
compiler that the token "Baz" should stand on its own and not be treated 
as the beginning of an elaborate name specifier even though there is a 
name resolution operator after it.

V
-- 
I do not respond to top-posted replies, please don't ask

[toc] | [prev] | [next] | [standalone]


#15205

FromKalle Olavi Niemitalo <kon@iki.fi>
Date2012-04-04 01:15 +0300
Message-ID<87zkastqbq.fsf@Niukka.kon.iki.fi>
In reply to#15199
Victor Bazarov <v.bazarov@comcast.invalid> writes:

> You could try adding a 'using' declaration before the 'friend':
>
>     class Bar
>     {
>        using ::Foo;
>        friend Baz Foo<>(Bar*);
>     };
>
> (I've not tried it).

GCC 4.6.3 doesn't like that.

  friend.cc:9:16: error: using-declaration for non-member at class scope

> Or you could put 'Baz' in parentheses:
>
>     class Bar
>     {
>        friend (Baz) ::Foo<>(Bar*);
>     };
>
> (I've not tried it either).

That doesn't work either.

  friend.cc:9:16: error: ISO C++ forbids declaration of 'Baz' with no type [-fpermissive]
  friend.cc:9:16: error: 'Baz' is neither function nor member function; cannot be declared friend
  friend.cc:9:16: error: expected ';' at end of member declaration
  friend.cc:9:30: error: ISO C++ forbids declaration of 'Foo' with no type [-fpermissive]
  friend.cc:9:30: error: invalid use of '::'

In general, you cannot put parentheses around types in
declarations.  For example, (int) x; does not declare a variable.
Instead, put the parentheses around the name being declared, or
around the whole declarator:

  class Baz {};

  template<class T> Baz Foo(T*);
  class Bar;
  template<> Baz Foo(Bar*);

  class Bar
  {
    friend Baz (::Foo<>)(Bar*);
    friend Baz (::Foo<>(Bar*)); /* same thing */
  };

It seems one could also use a typedef, at least with GCC:

  class Bar
  {
    typedef Baz foofun(Bar*);
    friend foofun ::Foo<>;
  };

However, I'm not sure how well that kind of friend declaration
conforms to the standards, especially with the template argument
deduction.

[toc] | [prev] | [next] | [standalone]


#15230

FromAndrey Dj <djdron@gmail.com>
Date2012-04-05 07:09 -0700
Message-ID<14983223.246.1333634973273.JavaMail.geo-discussion-forums@ynej3>
In reply to#15205
<b>Kalle Olavi Niemitalo</b>

>   class Bar
>   {
>     friend Baz (::Foo<>)(Bar*);
>     friend Baz (::Foo<>(Bar*)); /* same thing */
>   };

Thank you very much, this works! :)

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c++


csiph-web