为什么C ++ 11删除的函数参与重载parsing?

为什么C ++ 11使“ delete d”函数参与重载parsing ?
为什么这是有用的? 换句话说,为什么他们隐藏起来而不是完全被删除?

= delete语法的一半目的是防止人们用特定的参数调用某些函数。 这主要是为了防止在某些特定情况下的隐式转换。 为了禁止特定的超载,它必须参与重载parsing。

你引用的答案给了你一个完美的例子:

 struct onlydouble { onlydouble(std::intmax_t) = delete; onlydouble(double); }; 

如果delete完全delete函数,这将使= delete语法相当于这个:

 struct onlydouble2 { onlydouble2(double); }; 

你可以这样做:

 onlydouble2 val(20); 

这是合法的C ++。 编译器会查看所有的构造函数; 没有一个直接采用整数types。 但其中一个可以在隐式转换后进行。 所以它会这么叫。

 onlydouble val(20); 

不是合法的C ++。 编译器会查看所有的构造函数,包括delete函数。 它将通过std::intmax_t (它将完全匹配任何整数文字)看到完全匹配。 所以编译器会select它,然后立即发出一个错误,因为它select了一个delete d函数。

= delete意味着“我禁止这个”,而不仅仅是“这不存在”。 这是一个更强大的声明。

我问为什么C ++标准说=删除意味着“我禁止这个”,而不是“这不存在”

这是因为我们不需要特殊的语法来说“这不存在”。 我们通过简单地不宣称特定的“这个”是隐含的。 “我禁止这个”代表一个没有特殊语法就无法实现的结构。 所以我们得到特殊的语法来说“我禁止这个”,而不是其他的东西。

只有明确的“这个不存在”语法才能获得的唯一function是防止某人稍后宣布它存在。 而这只是没有足够的需要自己的语法。

否则没有办法声明复制构造函数不存在,并且它的存在会导致无意义的歧义。

复制构造函数是一个特殊的成员函数。 每个类都有一个拷贝构造函数。 就像他们总是有一个拷贝赋值操作符一样,移动构造函数等等

这些function存在; 问题只是称它们是否合法。 如果你试图说= delete意味着它们不存在,那么规范将不得不解释一个函数不存在的含义。 这不是规范处理的概念。

如果您尝试调用尚未被声明/定义的函数,那么编译器将会报错。 但是,由于未定义的标识符 ,将会出错,而不是因为“函数不存在”错误(即使您的编译器以这种方式报告)。 各种构造函数都是通过重载parsing来调用的,所以它们的“存在”就是在这方面处理的。

在任何情况下,都有一个通过标识符声明的函数,或者是一个构造函数/析构函数(也可以通过标识符声明,只是一个types标识符)。 运算符重载隐藏了语法糖背后的标识符,但它仍然存在。

C ++规范不能处理“不存在的函数”的概念。 它可以处理过载不匹配。 它可以处理超负荷的歧义。 但它不知道什么是不存在的。 所以= delete是根据更有用的“尝试调用这个失败”来定义的,而不是那些不太有用的“假装我从来没有写过这一行”的东西。

再次重读第一部分。 你不能这样做, “function不存在”。 这就是为什么这样定义的另一个原因:因为= delete语法的主要用例之一是能够强制用户使用某些参数types,显式强制转换等等。 基本上,要箔隐式转换。

你的build议不会这样做。

C ++工作草案2012-11-02没有提供这个规则的基本原理,只是一些例子

8.4.3删除的定义[dcl.fct.def.delete]

3 [ 例如 :可以强制执行非默认初始化和非整数初始化

 struct onlydouble { onlydouble() = delete; // OK, but redundant onlydouble(std::intmax_t) = delete; onlydouble(double); }; 

结束示例 ]
[ 示例 :可以通过使用用户声明的运算符new的删除定义来防止在某些新的expression式中使用类。

 struct sometype { void *operator new(std::size_t) = delete; void *operator new[](std::size_t) = delete; }; sometype *p = new sometype; // error, deleted class operator new sometype *q = new sometype[3]; // error, deleted class operator new[] 

结束示例 ]
[ 例如 :通过使用复制构造函数和复制赋值运算符的已删除定义,然后提供移动构造函数和移动赋值运算符的默认定义,可以使类不可复制,即仅移动。

 struct moveonly { moveonly() = default; moveonly(const moveonly&) = delete; moveonly(moveonly&&) = default; moveonly& operator=(const moveonly&) = delete; moveonly& operator=(moveonly&&) = default; ~moveonly() = default; }; moveonly *p; moveonly q(*p); // error, deleted copy constructor 

结束示例 ]