隐含的特殊功能:什么时候它们会形成错误?

时间:2018-03-16 11:37:39

标签: c++ c++11 c++03

在ISO 国际标准 for C ++ 11中,给出了c ++ 2003和C ++ 2011之间差异的摘要。其中一个不同之处是:

  

[diff.cpp03.special]

     

更改:隐式声明的特殊成员函数在隐式定义时被定义为已删除   本来就是不合格的。

     

基本原理:改进模板参数扣除失败。

     

对原始功能的影响:在不需要定义的上下文中使用这些特殊成员函数之一的有效C ++ 2003程序(例如,在无法评估的表达式中)不良形成。

我没有看到这种特殊功能在哪种情况下会形成错误,以及它如何打破SFINAE。所以我的问题归结为:

  • 为什么这样的改变"改善模板参数扣除失败"
  • 你能举个例子吗?

2 个答案:

答案 0 :(得分:21)

struct NonCopyable {
  NonCopyable() {}
private:
  NonCopyable(const NonCopyable &);
};

struct S {
  NonCopyable field;
} s;

int main() {
  return sizeof S(s);
}

这里,NonCopyable是不可复制的,但是当显式提供复制构造函数时,不会创建隐式复制构造函数。

对于S,用户不提供复制构造函数,因此创建了隐式复制构造函数。此复制构造函数将复制NonCopyable field字段,该字段是不可复制的,因此复制构造函数将格式不正确。

main中,采用复制构造的S对象的大小。这需要S的复制构造函数,但实际上并没有调用它。

在C ++ 03中,这是有效的。复制构造函数不正确,但由于没有复制,所以没关系。

在C ++ 11中,这是无效的。复制构造函数被标记为已删除,因此即使作为sizeof的操作数也不能使用。

这允许元编程检测类型是否可复制,这在C ++ 03中是不可能的。

答案 1 :(得分:1)

如果你想要一个具体的例子,std :: pair通常很容易复制,但如果其中一个成员是std :: unique_ptr,则unique_ptr不允许从Lvalue复制,所以它将是格式错误:因此std :: pair默认左值复制操作会自动删除。