Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 是否可能有相互参照的C++;模板? 问题_C++_Templates_C++14 - Fatal编程技术网

C++ 是否可能有相互参照的C++;模板? 问题

C++ 是否可能有相互参照的C++;模板? 问题,c++,templates,c++14,C++,Templates,C++14,我有以下两个结构声明: template <typename T> struct Yin { T *m_ptr; }; template <typename T> struct Yang { T *m_ptr; }; 但是我想这样做,而不需要将Yin和Yang硬编码到彼此的定义中,因此X类似于Yin 我可以在没有模板参数的情况下执行此操作,例如: struct Yin; struct Yang; struct Yin { Yang *m_ptr; };

我有以下两个结构声明:

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

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

但是我想这样做,而不需要将
Yin
Yang
硬编码到彼此的定义中,因此
X
类似于
Yin

我可以在没有模板参数的情况下执行此操作,例如:

struct Yin;
struct Yang;

struct Yin {
  Yang *m_ptr;
};

struct Yang {
  Yin *m_ptr;
};
但我的实际用例要复杂得多,我真的很想让它通用化。有人知道实现这一目标的方法吗?或者可能看到一些明显的我遗漏的东西

我将这个问题标记为
c++14
,因为我正在用
-std=c++1y
编译相关代码,我很乐意使用任何c++11/c++14特性来实现这一点

一个不编译的潜在解决方案。 下面是一个解决方案,它看起来应该可以工作,但无法编译(并向我提供无用的错误消息):

模板
结构阴{
T*m_ptr;
};
模板
结构杨{
T*m_ptr;
};
模板
结构结{
使用类型=A;
};
模板
使用Tie=typename knot::type;
int main(){
//foo.cc:13:39:错误:“knot”中没有名为“type”的类型
//使用类型=A;
//                 ~~~~~~~~~~~~~~~~~~~~~^~~~
领带x;
}
是 当
T
是模板类型且
void
是模板参数时,专门化阴阳,这会导致
Yin
指向一个
Yang
,反之亦然,但不明确引用另一个,因此您可以拥有任意数量的这些类型。只有一个专业

//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;
};
//特殊递归情况
模板
结构阴
{
其他*m_ptr;
};
模板
结构杨
{
其他*m_ptr;
};
但是,这些专门化适用于任何
模板
类型,因此我们需要将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 {} 
模板结构为_yinyang:public std::false_type{};
模板结构为_yinyang:public std::true_type{};
模板结构为_yinyang: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;
};
//这是阴+特化
模板
结构阴{
T*m_ptr;
};
模板结构为_yinyang:public std::true_type{};
模板
结构阴
{
其他*m_ptr;
};
现在阴和阳只引用它们自己,添加新的递归指针类型很简单。此处的汇编证明:


“但是等等!”你惊叫道,然后我必须复制我所有的成员!不是简单地将
Yin
拆分成一个包含共享成员的类,并让它从
Yin\u specialmembers
继承,后者包含需要专门化的成员。简单。

是的。首先,教
Yin
Yang
如何接受存储类型的任意映射:

template<class T>struct identity{using type=T;};

template <typename T, template<class>class Z=identity>
struct Yin {
  template<class U>using Z_t=typename Z<U>::type;
  Z_t<T> *m_ptr;
};

template <typename T, template<class>class Z=identity>
struct Yang {
  template<class U>using Z_t=typename Z<U>::type;
  Z_t<T> *m_ptr;
};
它接受两个东西,比如
Yin
Yang
,并在第二个参数中切换每次应用哪一个

为了测试它:

using yin = Yin< void, flopper<Yin, Yang>::template flip >;
using yang = Yang< void, flopper<Yang, Yin>::template flip >;
yin a = {nullptr};
yang b = {&a};
使用yin=yin;
使用yang=yang;
yina={nullptr};
杨b={&a};
我们创建类型,然后

尝试至少在该版本的gcc中使用

请注意,可以更改无穷远处的类型--
void
,并生成不同的类型


在这种情况下,
之间存在连接,除此映射之外,不需要对这两种类型进行任何处理。唯一的连接在
flopper
元模板类型函数中。映射类型函数甚至相对不可知于
Yin
Yang
——我使用了它们的名称,但没有必要这样做。

考虑到右侧的
X
Y
将具有无限的级别,我不明白如果没有明确的专门化,这是怎么可能的。几乎,使用额外的继承级别:@dyp nice!天生聪明。编辑:嗯。。我误解了。这不太管用。虽然很近!我无法让它实际使用这些类型,只能使用这种额外的继承级别。但是,我可以使类型
foo
bar
兼容:我得到了这个:,这是正确的想法吗?可能想添加一些SFINAE,这样它就不会意外发现误报,但我认为这很好……”但我希望这样做,而不必将阴阳硬编码到彼此的定义中“@LightnessRacesinOrbit:我不确定这是否适用于模板专门化,我们必须看看OP说了什么。我想不出任何其他方法。在我的真实代码中,有几个类的行为“像一个阴”和几个类的行为“像一个阳”,我希望能够组合它们中的任何一个。所以,这种方法需要很多专门知识。@LightnessRacesinOrbit:Complaintaddressed@scpayson:它现在扩展到N个类型
template<class T>struct identity{using type=T;};

template <typename T, template<class>class Z=identity>
struct Yin {
  template<class U>using Z_t=typename Z<U>::type;
  Z_t<T> *m_ptr;
};

template <typename T, template<class>class Z=identity>
struct Yang {
  template<class U>using Z_t=typename Z<U>::type;
  Z_t<T> *m_ptr;
};
template<
  template<class, template<class>class>class Yin,
  template<class, template<class>class>class Yang
>
struct flopper {
  template<class T> struct flip {
    using type = Yang<T, flopper<Yang, Yin>::template flip>;
  };
};
using yin = Yin< void, flopper<Yin, Yang>::template flip >;
using yang = Yang< void, flopper<Yang, Yin>::template flip >;
yin a = {nullptr};
yang b = {&a};