本文介绍了具有模板组成的CRTP编译检测的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm stuck with templates problems since few days and you solve each of my problem at a time so thank you in advance.

所以我有一个模板( tl1 )关心 uml组成和另一个模板( tl2 )是由 uml组成的

所以我的目标是如果组成对象不是 tl2 派生的,如果 typename D 不是派生的 tl1

So I've a template (tl1) who care about a uml composition, and another template (tl2) wich is the uml composed
So my goal is to not compile if the composed object is not a derived of tl2 and if typename D is not a tl1 derived.

遵循此和此我有以下代码:

Following this post and the help of this one I've got the following code:

#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>  {

};

我的问题是这个编译的很好,我不想。
我不想编译,因为来自 tl1< D,T> 中的 D tl1 导出


实际上是类cl1:public tl1< int,cl2> 不正确,但可以编译。那么为什么呢?

如果将 cl1 更改为:

My problem is this compile very well and I would like not. I would like not compile because D from tl1<D, T> must derived from tl1.
And actually class cl1 : public tl1<int, cl2> is not correct but it compile. So why?
It doesn't compile if I change cl1 to:

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

我了解更改后为什么不进行编译,但是我不明白为什么在进行更改之前就进行了编译。

I understand why it doesn't compile after the change, but I do not understand why it compile before.

事实是 tl1 tl2 在库中,因此我要在库中执行所有检查。我将无法控制派生,因此我想确保实现 tlX派生

The fact is tl1 and tl2 will be in library, so I want to perform all checks in the library. I will not have control over derived so I'd like to be sure that implementation is tlX derived.

再次感谢您的时间。

昆汀

Thank you for your time again.
Quentin

推荐答案

做您想做的事情的问题是周期性依赖性。就我所知, std :: is_base_of 要求使用完整的类型。

The problem with doing what you are trying to do is cyclical dependencies. std::is_base_of requires a complete type in order to work as far as I am aware.

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

Your code has TWO restrictions in tl1..


  • T必须继承tl2

  • D必须继承tl1

最后,它看起来像这样:

In the end, it ends up looking like:

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

tl1<T, D> where D inherits tl1<T, D> where D inherits tl1<T, D>

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

In other words, D will never be defined because Tl1 requires the definition of D as a template parameter but D must inherit from Tl1 which requires it.

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

Now if you remove the restriction on D, then the following code will compile as it should because the first restriction is met. However, if you uncomment the static_assert in tl1, it will NEVER compile because the definition of D depends on the definition of tl1 which depends on the definition of D and so on.. and so forth..

您会收到类似这样的错误:

You'd get an error like:

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*));
};

它将给您错误:

递归地替换'template< class T>静态字符is_base_of< B,D> :: Check(is_base_of< B,D> :: dummy< T> *)[with T =< missing>]'

在我看来,这更清楚发生了什么。

Which in my opinion is much clearer as to what is happening.

TLDR:您不能。

这篇关于具有模板组成的CRTP编译检测的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-27 23:27