Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"elaborated type refers to typedef" error when trying to befriend a typedef

Let's say I have the following piece of code (a simple CRTP class hierarchy). I want to typedef the base class type to save myself typing (in my actual code, I use the base class type more than once and the base class takes several template parameters), and I need to befriend the base class since I want to keep the implementation private.

template< class D >
class Base
{

public:

    void foo() { *static_cast< D * >(this)->foo_i(); }

};

template< class T >
class Derived : public Base< Derived< T > >
{

public:

    typedef class Base< Derived< T > > BaseType;

private:

    // This here is the offending line 
    friend class BaseType;

    void foo_i() { std::cout << "foo\n"; }

};

Derived< int > crash_dummy;

clang says:

[...]/main.cpp:38:22: error: elaborated type refers to a typedef
    friend class BaseType;
             ^
[...]/main.cpp:33:44: note: declared here
    typedef class Base< Derived< T > > BaseType;

How do I fix this? I noticed that I could simply type out the whole thing just for the friend class declaration and it works fine, but even a tiny bit of duplicated code makes me feel a tad uncomfortable, so I'm looking for a more elegant "proper" solution.

like image 298
jaymmer - Reinstate Monica Avatar asked Jan 31 '13 10:01

jaymmer - Reinstate Monica


2 Answers

I believe that this is not possible with C++03, but was added to C++11 in which you can simply omit the class keyword:

friend BaseType;
like image 194
Joseph Mansfield Avatar answered Sep 28 '22 09:09

Joseph Mansfield


Enable C++11 only and use friend BaseType

You cannot use friend class on typedef in C++03.

An elaborated-type-specifier shall be used in a friend declaration for a class(101)

101) The class-key of the elaborated-type-specifier is required.

elaborated-type-specifier:

class-key ::opt nested-name-specifieropt identifier

class-key ::opt nested-name-specifieropt templateopt template-id

enum ::opt nested-name-specifieropt identifier

typename ::opt nested-name-specifier identifier

typename ::opt nested-name-specifier templateopt template-id
like image 29
ForEveR Avatar answered Sep 28 '22 09:09

ForEveR