繁体   English   中英

具有模板组成的CRTP编译检测

[英]CRTP compile detection with template composition

几天以来,我一直困扰于模板问题,您一次解决了每个问题,因此在此先感谢您。

所以,我的模板( tl1谁在乎) uml composition ,和另一个模板( tl2 )至极是uml composed
所以我的目标是,如果不编composed对象不是derivedtl2 ,如果typename D不是tl1 derived

根据这一职位和这的帮助下一个我有下面的代码:

#include <type_traits>
#include <list>
#include <string>

template <typename T, typename C>
class tl2 ;

template <typename D, typename T>
class tl1 {
private:
    static_assert(std::is_base_of<tl2<T, D>, T>::value, "T should     inherit from tl2");
    std::list<T> mTs ;
    tl1() {} ;
    friend D ;
public:
    T & getTbyName() const ;
};

template <typename T, typename C>
class tl2 {
    //static_assert(std::is_base_of<tl1<C, T>, C>::value, "D should inherit from Database");
public:
    std::string getName() { return mName ; }
private:
    C & mC ;
    std::string mName ;
};

class cl1 ;

class cl2 : public tl2<cl2, int>  {

};
class cl1 : public tl1<int, cl2>  {

};

我的问题是此编译非常好,我不想这样做。 我想不能编译,因为Dtl1<D, T>必须derivedtl1
实际上, class cl1 : public tl1<int, cl2>是不正确的,但可以编译。 所以为什么?
如果将cl1更改为:

class cl1 : public tl1<int, cl2>  {    
    cl1() {}
};

我了解为什么更改后无法编译,但是我不明白为什么更改前无法编译。

事实是tl1tl2将在库中,所以我想在图书馆进行所有检查。 我将无法控制派生,因此我想确保implementationtlX derived

再次感谢您的宝贵时间。
昆汀

做您想做的事情的问题是循环依赖。 据我所知, std::is_base_of需要一个完整的类型才能工作。

您的代码在tl1中有两个限制。

  • T必须继承tl2
  • D必须继承tl1

最后,它看起来像:

tl1<T, D>其中D继承tl1<T, D>其中D继承tl1<T, D>

换句话说,永远不会定义D,因为Tl1要求将D的定义定义为模板参数,但是D必须继承自Tl1的要求。

现在,如果您删除了对D的限制,那么由于满足了第一个限制,下面的代码将按原样编译。 但是,如果取消注释tl1中的static_assert,则将永远不会编译,因为D的定义取决于tl1的定义,tl1取决于D的定义,依此类推。等等。

您会收到类似以下的错误:

invalid use of incomplete type 'class cl1'
     struct is_base_of
            ^
note: forward declaration of 'class cl1'

码:

#include <type_traits>
#include <list>
#include <string>

template <typename T, typename C>
class tl2 ;

template <typename D, typename T>
class tl1 {
private:
    static_assert(std::is_base_of<tl2<T, D>, T>::value, "T should     inherit from tl2");
    //static_assert(std::is_base_of<tl1, D>::value, "D should inherit from tl1");
    std::list<T> mTs ;
    friend D ;
public:
    tl1() {}
    T & getTbyName() const ;
};

template <typename T, typename C>
class tl2 {
    //static_assert(std::is_base_of<tl1<C, T>, C>::value, "D should inherit from Database");
public:
    std::string getName() { return mName ; }
private:
    //C & mC ;
    std::string mName ;
};


class cl1;

class cl2 : public tl2<cl2, cl1>  {
    public:
        cl2() {}
};

class cl1 : public tl1<cl1, cl2>  {
    public:
        cl1() {}
};

int main() {
    cl1 a;
    cl2 b;
    return 0;
}

如果将std::is_base_of替换为:

template<class B, class D>
struct is_base_of
{
  template<typename T> struct dummy {};
  struct Child : D, dummy<int> {};

  static B* Check (B*);
  template<class T> static char Check (dummy<T>*);

  static const bool value = (sizeof(Check((Child*)0)) == sizeof(B*));
};

它会给你错误:

recursively required by substitution of 'template<class T> static char is_base_of<B, D>::Check(is_base_of<B, D>::dummy<T>*) [with T = <missing>]'

我认为哪个更清楚发生了什么。

TLDR:不能。

您的代码可以编译,因为静态断言中没有错误。

cl1专门用于tl1与

T = cl2从继承tl2<cl2, int> D = int

然后您验证

std::is_base_of<tl2<T, D>, T>::value == true

因此,让我们在这里替换TD

std::is_base_of<tl2<cl2, int>, cl2>::value == true

那是正确的。

换句话说,您的静态断言可能没有检查应做的事情。 截至目前,我有点困惑您想要实现的目标。 我将为您以前的问题提供答案,但您应该认真考虑使自己的名字更清楚。 这将有助于理解您打算实现的目标。

在@Brandon反馈之后,我想您可能正在寻找: http ://ideone.com/H4hm3O

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM