Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > problem with template friend partial specialization

Reply
Thread Tools

problem with template friend partial specialization

 
 
Andrey Dj
Guest
Posts: n/a
 
      04-02-2012
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?
 
Reply With Quote
 
 
 
 
Victor Bazarov
Guest
Posts: n/a
 
      04-03-2012
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
 
Reply With Quote
 
 
 
 
Kalle Olavi Niemitalo
Guest
Posts: n/a
 
      04-03-2012
Victor Bazarov <(E-Mail Removed)> 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.
 
Reply With Quote
 
Andrey Dj
Guest
Posts: n/a
 
      04-05-2012
<b>Kalle Olavi Niemitalo</b>

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


Thank you very much, this works!
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Template template partial specialization Hizo C++ 17 03-07-2011 08:09 AM
how to do partial specialization template for non member method template vj C++ 1 12-20-2010 11:57 AM
Partial Specialization as a friend ...? Belebele C++ 3 11-02-2007 06:47 PM
syntax problem for partial template specialization for a template class. toton C++ 1 12-28-2006 04:08 PM
Problem with Partial Template Specialization and Borland C++ Builder Alex@L C++ 6 01-20-2005 08:34 PM



Advertisments