首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >混合typedef和CRTP?

混合typedef和CRTP?
EN

Stack Overflow用户
提问于 2012-12-24 22:20:00
回答 2查看 430关注 0票数 4

考虑以下示例:

代码语言:javascript
复制
#include <iostream>
#include <iostream>
#include <type_traits>

template<typename Type, template<typename> class Crtp>
class Base
{
    public:
        typedef int value;

        // f1: OK
        // Expected result: casts 4.2 to Base<Type, Crtp>::value
        value f1() {return 4.2;}

        // f2: NOT OK
        // Expected result: casts 4.2 to Crtp<Type>::value
        // But f2 does not compile: no type named 'value' 
        // in 'class Derived<double>'
        typename Crtp<Type>::value f2() {return 4.2;} 
};

template<typename Type>
class Derived : public Base<Type, Derived>
{
    public:
        typedef Type value;
};

int main()
{
    Derived<double> a;
    std::cout<<a.f1()<<std::endl;
    std::cout<<a.f2()<<std::endl;
    return 0;
}

如何解决这个问题( Base类未知的Derived类型定义)?

编辑:我发现了一个非常简单的技巧。谁能给我解释一下为什么下面的版本是有效的,而之前的版本不起作用?这个技巧是适用于标准的C++11,还是因为编译器的工作方式(这里是g++ 4.7.1)?

代码语言:javascript
复制
#include <iostream>
#include <iostream>
#include <type_traits>

template<typename Type, template<typename> class Crtp>
class Base
{
    public:
        typedef int value;
        value f1() {return 4.2;}
        template<typename T = Crtp<Type>> typename T::value f2() {return 4.2;}
};

template<typename Type>
class Derived : public Base<Type, Derived>
{
    public:
        typedef Type value;
};

int main()
{
    Derived<double> a;
    std::cout<<a.f1()<<std::endl;
    std::cout<<a.f2()<<std::endl;
    return 0;
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-12-24 22:25:09

您必须使用在定义Base之前声明的包装类(这里是value_getter)。然后,可以在定义Derived之前对其进行专门化

代码语言:javascript
复制
template<typename T>
struct value_getter;

template<typename Type, template<typename> class Crtp>
class Base
{
    public:
        typedef int value;

        value f1() {return 4.2;}

        // in 'class Derived<double>'
        typename value_getter<Crtp<Type> >::value f2() {return 4.2;} 
};

template<typename Type>
class Derived;

template<typename Type>
struct value_getter<Derived<Type> > {
    typedef Type value;
};

template<typename Type>
class Derived : public Base<Type, Derived>, public value_getter<Derived<Type> >
{
    public:
};

它不是很漂亮,但至少它可以工作。

票数 3
EN

Stack Overflow用户

发布于 2012-12-24 23:08:59

您的技巧之所以有效,是因为在完成类派生之后,f2现在直到实际使用时才会被实例化。

在您的特定示例中,我可能只建议这样做:

代码语言:javascript
复制
#include <iostream>
#include <iostream>
#include <type_traits>

template<typename Type, template<typename> class Crtp>
class Base
{
    public:
        typedef int value;

        value f1() {return 4.2;}

        Type f2() {return 4.2;} 
};

template<typename Type>
class Derived : public Base<Type, Derived>
{
    public:
        typedef Type value;
};

int main()
{
    Derived<double> a;
    std::cout<<a.f1()<<std::endl;
    std::cout<<a.f2()<<std::endl;
    return 0;
}

但是,您的实际代码可能还有其他需求,这使得这一点不切实际。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14022493

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档