几天以来,我一直困扰于模板问题,您一次解决了我的每一个问题,所以在此先谢谢您。
因此,我有一个关心tl1
的模板(uml composition
),而另一个模板(tl2
)是uml composed
因此,我的目标是如果composed
对象不是derived
的tl2
,并且typename D
不是tl1 derived
,则不进行编译。
在此post和此one的帮助之后,我得到了以下代码:
#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> {
};
我的问题是此编译非常好,我不想这样做。
我不想编译,因为
D
中的tl1<D, T>
必须来自derived
中的tl1
。实际上
class cl1 : public tl1<int, cl2>
是不正确的,但可以编译。所以为什么?如果将
cl1
更改为:它不会编译:class cl1 : public tl1<int, cl2> {
cl1() {}
};
我了解为什么更改后无法编译,但是我不明白为什么更改前无法编译。
事实是
tl1
并且tl2
将在库中,因此我想在库中执行所有检查。我将无法控制派生,因此我想确保implementation
是tlX derived
。再次感谢您的宝贵时间。
昆汀
最佳答案
做您想做的事情的问题是循环依赖。据我所知,std::is_base_of
需要完整的类型才能工作。
您的代码在tl1中有两个限制。
T必须继承tl2
D必须继承tl1
最后,它看起来像:
D继承tl1<T, 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:不能。
关于c++ - 具有模板组成的CRTP编译检测,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35683456/