继承CRTP中派生的type_trait:派生类型尚未完成(尚未完成)

时间:2018-01-09 04:04:55

标签: 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设置在一个单独的特质类中。

1 个答案:

答案 0 :(得分:1)

实例化如下:

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并且与您的专业化相匹配,则会typeB

要从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;}
};

然后加入

npm