std :: pair抱怨不完整的类型

时间:2014-09-19 01:53:59

标签: c++ c++11 boost

如何编译以下代码?

#include <type_traits>
#include <utility>

struct A;

template<typename T>
struct B{
    T* p;

    B& operator=(B&&);
    B& operator=(T&&);
};

int main(){
    //typedef B<A> type;// fine
    typedef B<std::pair<A, A>> type;// error

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

    return 0;
}

PS:B型模拟boost :: recursive_wrapper,由于同样的原因无法编译。

2 个答案:

答案 0 :(得分:8)

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):

  

如果重载解析过程可以确定正确的功能   如果没有实例化类模板定义就调用它   未指定实例化是否实际发生。

答案 1 :(得分:2)

在您在另一个声明中使用它之前,您必须实际输入A的整个声明。前瞻性参考不够。