7

假设我有以下代码(一个简单的 CRTP 类层次结构)。我想对基类类型进行 typedef 以节省自己的输入(在我的实际代码中,我不止一次使用基类类型,并且基类需要几个模板参数),并且我需要与基类成为朋友,因为我想保留实现私有。

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;

铿锵声 说:

[...]/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;

我该如何解决?我注意到我可以简单地为朋友类声明输入整个内容并且它工作正常,但即使是一点点重复的代码也会让我感到有点不舒服,所以我正在寻找一个更优雅的“正确”解决方案.

4

3 回答 3

11

我相信这在 C++03 中是不可能的,但被添加到 C++11中,您可以在其中简单地省略class关键字:

friend BaseType;
于 2013-01-31T10:38:57.057 回答
3

仅启用 C++11 并使用friend BaseType

您不能在 C++03 中的 typedef 上使用朋友类。

在类的友元声明中应使用详细类型说明符(101)

101) 详细类型说明符的类键是必需的。

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
于 2013-01-31T10:39:10.930 回答
1

实际上,您可以在 C++11 之前的 C++ 中做到这一点,但它需要一个相当复杂(哈哈)的解决方法,首先声明这个“助手”:

template< class T > struct ParamTypeStruct { typedef T ParamType; };

然后,你的朋友声明:

friend class ParamTypeStruct< BaseType >::ParamType;
于 2013-10-14T17:35:35.747 回答