问题

我有以下两个struct声明:

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,因为我正在用-std=c++1y用clang编译相关的代码,并且很高兴使用任何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进行操作,这会使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 {}
然后是这个可怕的部分,它极其复杂和丑陋,并且需要在Yin/Yang类型上使用无意义的额外模板参数:
//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/

10-09 15:07