c++ - 在 CRTP : type of Derived is not complete (yet) 中继承 Derived 的 type_trait

标签 c++ c++14 typetraits crtp

库代码

我的图书馆有一个 CRTP 类 B<Derived> .
我创建了一个 Trait<T>使用户能够更改 B 行为的类.
默认设置为 int . ( #1 )

#include <iostream>
#include <string>
//B and Trait (library class)
template<class Derived> class B;
template<class T>class Trait{
    public: using type = int;   //<-- default setting    //#1
};   
template<class Derived> class B{
    public: using type = typename Trait<Derived>::type;  //#2
    public: type f(){return 1;}
};  

用户代码 ( full coliru demo )

然后,我创建一个新类 C使用新设置 std::string . ( #3 )
它工作正常。

//C (user1's class)
template<class Derived> class C ;
template<class Derived>class Trait<C<Derived>>{
    public: using type = std::string;             //#3
};
template<class Derived> class C : public B<Derived>{};

最后,我创建了一个新类 D .
我要D导出C的设置即 std::string (不是 int )。
然而,它在 $ 处不可编译。 .

//D (user2's class)
class D : public C<D>{                            //#4
    public: type f(){return "OK";}                //#5
    //$ invalid conversion from 'const char*' to 'B<D>::type {aka int}' 
};
int main(){
    D dt;
    std::cout<< dt.f() <<std::endl;
}

我的理解

粗略地说,这是我对编译过程的理解:-

  • 就在class D之前( #4 ),它不知道 D .
  • #4 , 身份 D::type , 它查找 C<D>::type .
    最后发现定义在B<D>::type中在#2 .
  • 来自 #2 , 它移动到 #1 处的定义并找到 type = int .
    因此 D::type = int .
  • 请注意 #3忽略,因为此时(#4#5),D仍然不完整。
    编译器仍然不能完全识别 D源自 C<something> ... 然而。

enter image description here

问题

如何让D自动继承Trait来自 C 的设置没有明确定义另一个模板特化 Trait<D>

换句话说,如何制作#3未忽略 D

Trait可能不是一个好的设计(?),但我更愿意让 type设置在一个单独的特征类中。

最佳答案

实例化是这样的:

D -> C<D> -> B<D> -> Traits<D>

Traits<D>与您对 Traits<C<Derived>> 的部分特化不匹配

如果将其更改为 template<class Derived> class C : public B<C<Derived>>{};这将依次实例化 Traits<C<D>>这将与您的专业相匹配,您将获得 std::string作为type .

B得到 child 你可以使用。

template <typename... T>
struct getChild;

template <template <typename... T> typename First, typename... Rest>
struct getChild<First<Rest...>> { using child = typename getChild<Rest...>::child; };

template <typename First>
struct getChild<First> { using child = First; };

然后加入

template<class Derived> class B{
    public: using type = typename Trait<Derived>::type;
    using child = typename getChild<Derived>::child;
    public: type f(){return 1;}
};

关于c++ - 在 CRTP : type of Derived is not complete (yet) 中继承 Derived 的 type_trait,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48161273/

相关文章:

c++尝试反向打印数组时出现段错误

c++ - 如何在任何类中创建比较器函数,就像我们在 c++ STL 中的priority_queue 中创建比较器函数一样

c++ - 类成员函数作为继承情况下的模板参数

c++ - 使用引用作为通用参数从通用 lambda 创建线程

c# - 是否有 C++ std::is_same 类模板的 C# 类似物?

c++ - String 和 Int 之间的模板冲突

c++ - 在魔数(Magic Number)上不需要命名常量的情况

C++ 流运算符问题

c++ - 如何在代码中使用eclipse项目变量

c++ - 如何判断一个类型是否派生自模板类?