C++ 静态多态性 (CRTP) 和使用派生类的 typedef
我阅读了 维基百科文章,内容涉及 C++ 中奇怪的重复模板模式,用于执行静态(阅读:编译时)多态性.我想概括它,以便我可以根据派生类型更改函数的返回类型.(这似乎应该是可能的,因为基类型知道模板参数的派生类型).不幸的是,以下代码无法使用 MSVC 2010 进行编译(我现在无法轻松访问 gcc,所以我还没有尝试过).有人知道为什么吗?
I read the Wikipedia article about the curiously recurring template pattern in C++ for doing static (read: compile-time) polymorphism. I wanted to generalize it so that I could change the return types of the functions based on the derived type. (This seems like it should be possible since the base type knows the derived type from the template parameter). Unfortunately, the following code won't compile using MSVC 2010 (I don't have easy access to gcc right now so I haven't tried it yet). Anyone know why?
template <typename derived_t>
class base {
public:
typedef typename derived_t::value_type value_type;
value_type foo() {
return static_cast<derived_t*>(this)->foo();
}
};
template <typename T>
class derived : public base<derived<T> > {
public:
typedef T value_type;
value_type foo() {
return T(); //return some T object (assumes T is default constructable)
}
};
int main() {
derived<int> a;
}
顺便说一句,我有一个使用额外模板参数的变通方法,但我不喜欢它――在继承链上传递许多类型时它会变得非常冗长.
BTW, I have a work-around using extra template parameters, but I don't like it---it will get very verbose when passing many types up the inheritance chain.
template <typename derived_t, typename value_type>
class base { ... };
template <typename T>
class derived : public base<derived<T>,T> { ... };
MSVC 2010 在这种情况下给出的错误消息是 error C2039: 'value_type' : is not a member of 'derived
The error message that MSVC 2010 gives in this situation is error C2039: 'value_type' : is not a member of 'derived<T>'
g++ 4.1.2(通过codepad.org)说error: no type named 'value_type' in 'classderived
g++ 4.1.2 (via codepad.org) says error: no type named 'value_type' in 'class derived<int>'
推荐答案
derived
在您将其用作其基类列表中 base
的模板参数时是不完整的.
derived
is incomplete when you use it as a template argument to base
in its base classes list.
一种常见的解决方法是使用特征类模板.这是你的例子,特征化.这显示了如何通过特征使用派生类中的类型和函数.
A common workaround is to use a traits class template. Here's your example, traitsified. This shows how you can use both types and functions from the derived class through the traits.
// Declare a base_traits traits class template:
template <typename derived_t>
struct base_traits;
// Define the base class that uses the traits:
template <typename derived_t>
struct base {
typedef typename base_traits<derived_t>::value_type value_type;
value_type base_foo() {
return base_traits<derived_t>::call_foo(static_cast<derived_t*>(this));
}
};
// Define the derived class; it can use the traits too:
template <typename T>
struct derived : base<derived<T> > {
typedef typename base_traits<derived>::value_type value_type;
value_type derived_foo() {
return value_type();
}
};
// Declare and define a base_traits specialization for derived:
template <typename T>
struct base_traits<derived<T> > {
typedef T value_type;
static value_type call_foo(derived<T>* x) {
return x->derived_foo();
}
};
您只需要为用于 base
的模板参数 derived_t
的任何类型特化 base_traits
并确保每个特化提供base
需要的所有成员.
You just need to specialize base_traits
for any types that you use for the template argument derived_t
of base
and make sure that each specialization provides all of the members that base
requires.
相关文章