2014-09-19 123 views
4

如何编译下面的代码? PS:类型B模拟boost :: recursive_wrapper,由于相同的原因,它无法编译。std :: pair抱怨不完整的类型

+1

** 17.6.4.8/2 **特别是,在以下情况下效果未定义:... - 如果实例化模板组件时使用了不完整类型(3.9)作为模板参数,除非特别允许使用该组件,否则不得使用该组件。 – 2014-09-19 01:59:53

+0

@IgorTandetnik typedef本身不应该实例化'std :: pair '。 – 2014-09-19 02:00:57

+0

@ T.C .:为什么不呢? – jxh 2014-09-19 02:03:17

回答

7

typedef本身不是问题。编写struct foo; typedef std::pair<foo, foo> bar;完全合法。问题是与

noexcept(std::declval<type&>() = std::declval<type>()); 

这需要编译器执行重载分辨率operator=。由于重载解析的一部分也必须寻找可能的转换从B&&std::pair<A, A>&&,这需要实例化std::pair<A,A>(§14.7.1[temp.inst]/P6):

类模板专业化隐式实例,如果 类类型用于上下文中,该上下文需要完全定义的对象类型,或者类类型的完整性是否会影响程序的语义 。 [注意:特别是,如果 表达式的语义取决于类别 模板专用化的成员或基类列表,则隐含地生成类模板专用化 。例如,删除指向类类型 的指针取决于该类是否声明析构函数,并且指向类类型的指针之间的转换取决于涉及的两个类之间的关系 。 - 注完]

...,并通过§17.6.4.8[res.on.functions]/P2,这个实例会导致不确定的行为。

尽管不要求,编译器在此上下文中以实例std::pair<A, A>由于移动赋值运算符是精确匹配(§14.7.1[temp.inst]/P7):

如果过载解析过程可以确定要调用的正确函数 而不实例化类模板定义,未指定该实例是否实际发生。

+0

我想你明白这一点。那么如何绕过这个问题呢?你可以直接学习boost :: recursive_wrapper。 – cqdjyy01234 2014-09-19 02:13:23

+0

@ user1535111在这里,我无法理解一些编译器的行为。所以[我问过一个问题](http://stackoverflow.com/questions/25925551/gcc-and-clang-implicitly-instantiate-template-arguments-during-operator-overload)。 – 2014-09-19 02:47:36

2

在另一个声明中使用它之前,您必须实际上放入A的整个声明。前向参考是不够的。

+1

问题有时是不可能的。这是boost :: recursive_wrapper的值。 – cqdjyy01234 2014-09-19 02:10:08

+0

好的,对我来说,这解决了这个问题。 – donald 2016-10-18 09:41:15