c++ - 是否可以有相互引用的 C++ 模板?

标签 c++ templates c++14

问题

我有以下两个结构声明:

template <typename T>
struct Yin {
  T *m_ptr;
};

template <typename T>
struct Yang {
  T *m_ptr;
};

我想找到 XY这样我在替换后得到这样的东西:

// Not real C++ syntax
struct Yin<X> {
  Yang<Y> *m_ptr;
}

struct Yang<Y> {
  Yin<X> *m_ptr;
};

但我想在不进行硬编码的情况下这样做 YinYang进入彼此的定义,所以X会像 Yin<Yang<Yin<Yang<...>>>> .

我可以在没有模板参数的情况下这样做:

struct Yin;
struct Yang;

struct Yin {
  Yang *m_ptr;
};

struct Yang {
  Yin *m_ptr;
};

但我的实际用例要复杂得多,我真的很想让它通用。有谁知道实现这一目标的方法?或者可能看到我遗漏的明显东西?

我已将此问题标记为 c++14因为我正在用 clang 和 -std=c++1y 编译相关代码我很乐意使用任何 c++11/c++14 功能来完成这项工作。

无法编译的潜在解决方案。

这是一个看起来应该有效但无法编译的解决方案(并给我无用的错误消息):

template <typename T>
struct Yin {
  T *m_ptr;
};

template <typename T>
struct Yang {
  T *m_ptr;
};

template <template <class> class A, template <class> class B>
struct knot {
  using type = A<typename knot<B, A>::type>;
};

template <template <class> class A, template <class> class B>
using Tie = typename knot<A, B>::type;

int main() {
  // foo.cc:13:39: error: no type named 'type' in 'knot<Yin, Yang>'
  //  using type = A<typename knot<B, A>::type>;
  //                 ~~~~~~~~~~~~~~~~~~~~~^~~~
  Tie<Yin, Yang> x;
}

最佳答案

专阴阳为时T是模板类型,void是模板参数,导致Yin<Yang<void>>指向 Yang<Yin<void>>反之亦然,但没有对另一个的任何明确引用,因此您可以根据需要拥有任意数量的这些类型。只有一个专业。

//special recursive case
template <template<class> class other>
struct Yin<other<void>> 
{
    other<Yin<void>> *m_ptr;
};

template <template<class> class other>
struct Yang<other<void>> 
{
    other<Yang<void>> *m_ptr;
};

但是,这些特化适用于任何 template<void>类型,因此我们需要应用具有类型特征的 SFINAE:

template<template<class> class T> struct is_yinyang : public std::false_type {};
template<> struct is_yinyang<Yin> : public std::true_type {}; 
template<> struct is_yinyang<Yang> : public std::true_type {} 

然后是这个可怕的部分,它非常复杂和丑陋,需要阴/阳类型的一个毫无意义的额外模板参数:

//here's Yin + Specialization
template <typename T, class allowed=void>
struct Yin {
    T *m_ptr;
};
template<> struct is_yinyang<Yin> : public std::true_type {};

template <template<class,class> class other>
struct Yin<other<void,void>,typename std::enable_if<is_yinyang<other>::value>::type>
{
    other<Yin<void,void>,void> *m_ptr;
};

现在 Yin 和 Yang 只引用它们自己,添加新的递归指针类型是微不足道的。此处的编译证明:http://coliru.stacked-crooked.com/a/47ecd31e7d48f617

“但是等等!”你惊呼,那我得复制我所有的成员!不是很简单地拆分Yin与共享成员一起进入一个类,并让它继承自 Yin_specialmembers<T> ,其中包含需要特化的成员。很简单。

关于c++ - 是否可以有相互引用的 C++ 模板?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25538372/

相关文章:

c++ - 如何从我的自定义类继承

c++ - 如果在窗口关闭内调用 QThread finished() 发射失败

c++ - 链接和绑定(bind)有什么区别?

c++ - 为什么 C++ STL 如此大量地基于模板? (而不是在*接口(interface)*上)

c++ - 左值引用是否需要进行左值到右值的转换?

c++ - 使用变体类型列表调用 std::function

c++ - 为什么 C++ 初始化列表在大括号之前?

c++ - 克隆类型?

c++ - 模板简化

c++ - 使用变量的类型作为模板参数