C ++静态多态性(CRTP)并使用派生类的typedef [英] C++ static polymorphism (CRTP) and using typedefs from derived classes

查看:146
本文介绍了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,我有一个使用额外的模板参数的工作, 't like it ---当传递许多类型到继承链上时会非常详细。

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在这种情况下给出的错误消息是错误C2039:'value_type':不是'derived< T>'的成员

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 )说错误:没有类型命名'value_type'in'class derived< int>'

g++ 4.1.2 (via codepad.org) says error: no type named 'value_type' in 'class derived<int>'

推荐答案

c>在其基类列表中使用 作为模板参数时,不完整。

derived is incomplete when you use it as a template argument to base in its base classes list.

一个常见的解决方法是使用traits类模板。这里是你的例子,traitsified。这显示了如何通过traits使用派生类中的类型和函数。

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_traits 类型,您使用的 derived_t 基础的模板参数,并确保每个专业化提供所有成员 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.

这篇关于C ++静态多态性(CRTP)并使用派生类的typedef的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆