gpt4 book ai didi

c++ - CRTP 编译检测与模板组合

转载 作者:行者123 更新时间:2023-11-28 02:10:58 25 4
gpt4 key购买 nike

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

所以我有一个关心 tl1 的模板 ( uml composition ) , 和另一个模板 ( tl2 ) 是 uml composed
所以我的目标是如果composed不编译。对象不是 derivedtl2如果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() {}
};

我明白为什么改后编译不通过,但我不明白为什么之前编译通过。

事实是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:你不能。

关于c++ - CRTP 编译检测与模板组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35683456/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com