我正在尝试使用多重继承来实现一种CRTP(如果我很清楚它是什么)。
我的主要目标是以统一的方式访问每个子类的实例列表。
May问题似乎存在于名称空间利用率中。
以下是最简单版本的代码: http://ideone.com/rFab5
我真正的问题更类似于: http://ideone.com/U7cAf
我还有一个使用clang ++的警告:
test.cpp:28:63: warning: static data member specialization of 'instances' must originally be declared in namespace 'NS1'; accepted as a C++0x extension [-Wc++0x-extensions]
template <> std::list<NS1::Derived*> NS1::Base<NS1::Derived>::instances;
^
test.cpp:15:34: note: explicitly specialized declaration is here
static std::list<T*> instances;
问题已更新,因为使用命名空间行为不一样。
重新编辑问题以在Ideone上发布代码
答案 0 :(得分:1)
问题在于您尝试将列表变量定义错误。你需要为Base提供一个定义 - 一般来说 - 你不只是为Derived的子类定义它,除非它是一个明确的特化。
template<typename T> std::list<T*> NS1::Base<T>::instances;
编译没有错误。没有中间体或类似的东西。
答案 1 :(得分:0)
在构造函数中将Base()
和Intermediary()
更改为Base<U>()
和Intermediary<Derived>
会为GCC创建代码OK。
在第二种情况下,没有理由更改instances
的定义:模板与第一种情况相同。
答案 2 :(得分:0)
Afaik,您有以下选择。
首先,如果Intermediate
始终在派生类型上进行模板化,则不需要列表,因为它永远不会是派生类型最多的类型。如果它可以在其他类型上进行模板化/不进行派生,则可以添加默认的非类型bool模板参数,如下所示:
template<bool, class A, class B>
struct select_base{
typedef A type;
};
template<class A, class B>
struct select_base<false,A,B>{
typedef B type;
};
template<class T, bool IsDerived = false>
class Intermediate
: public select_base<IsDerived,
Base<T>,
Base<Intermediate<T> >
>::type
{
// ...
};
// derived use
class Derived : public Intermediate<Derived, true>
{
// ...
};
// non-derived use:
Intermediate<int> im;
如果中间类不是模板化的,并且尚未从Base
派生,则需要在最派生的类中再次从Base
派生:
class Derived : public Intermediate, public Base<Derived>
{
// ...
};
当中间体也来自Base
但不是模板化时,会出现一个大问题。您可以添加默认派生类型,但这会使非派生使用更难看:
#include <type_traits> // C++0x, use std::
//#include <tr1/type_traits> // C++03, use std::tr1::
struct nil_base{};
template<class Derived = nil_base>
class Intermediate
: public select_base<std::is_same<Derived,nil_base>::value,
Base<Intermediate<Derived> >, //
Base<Derived>
>::type
{
// ...
};
// derived use now without boolean flag
class Derived : public Intermediate<Derived>
{
// ...
};
// non-derived use a bit uglier
Intermediate<> im;
// ^^ -- sadly needed
答案 3 :(得分:0)
使用MinGW g ++ 4.4.1,MSVC 10.0和Comeau Online 4.3.10.1进行以下编译:
#include <list>
template <class T>
class Base
{
protected:
Base()
{
instances.push_back(static_cast<T*>(this));
}
private:
static std::list<T*> instances;
};
template <class U>
class Intermediary : public Base<U>
{
protected:
Intermediary()
:Base<U>()
{
}
};
class Derived : public Intermediary<Derived>
{
public:
Derived()
:Intermediary<Derived>()
{
}
};
template<class Derived> std::list<Derived*> Base<Derived>::instances;
int main()
{}
instances
定义会从您的问题中逐字复制。
我说作为艾萨克·牛顿,我没有提出任何假设!
干杯&amp;第h。,