为什么C++11删除的函数会参与过载解决
Why do C++11-deleted functions participate in overload resolution?
为什么C++11让"delete
d"函数参与过载解析
为什么这有用?或者换句话说,为什么它们被隐藏而不是被完全删除?
= delete
语法的一半目的是防止人们使用某些参数调用某些函数。这主要是为了防止某些特定场景中的隐式转换。为了禁止特定的过载,它必须参与过载解决。
你引用的答案给了你一个完美的例子:
struct onlydouble {
onlydouble(std::intmax_t) = delete;
onlydouble(double);
};
如果delete
完全删除了该函数,则= delete
语法等效于以下内容:
struct onlydouble2 {
onlydouble2(double);
};
你可以这样做:
onlydouble2 val(20);
这是合法的C++。编译器将查看所有构造函数;它们都没有直接采用整数类型。但他们中的一个可以在隐式转换后接受它。所以它会这么说。
onlydouble val(20);
这是而不是合法的C++。编译器将查看所有构造函数,包括delete
d构造函数。它将通过std::intmax_t
(它将与任何整数文本完全匹配(看到完全匹配。因此编译器会选择它,然后立即发出错误,因为它选择了delete
d函数。
= delete
的意思是"我禁止这样做",而不仅仅是"这不存在"。这是一个更强有力的说法。
我在问为什么C++标准说=删除意味着"我禁止这个"而不是"这个不存在">
这是因为我们不需要特殊的语法来说"这不存在"。我们通过简单地不声明特定的"这个"来隐含地得到这一点。"我禁止这样做"代表了一种结构,如果没有特殊语法,就无法实现。所以我们有特殊的语法来说"我禁止这个",而不是其他事情。
通过明确的"这不存在"语法,你唯一能获得的功能是防止有人后来宣布它存在。这还不够有用,不需要它自己的语法。
否则就无法声明复制构造函数不存在,并且它的存在可能会导致无意义的歧义。
复制构造函数是一个特殊的成员函数。每个类总是都有一个复制构造函数。正如他们总是有一个复制赋值运算符,移动构造函数等
这些功能是存在的;问题只是打电话给他们是否合法。如果你试图说= delete
意味着它们不存在,那么规范就必须解释函数不存在意味着什么。这不是规范处理的概念。
如果您试图调用尚未声明/定义的函数,那么编译器将出错。但它会因为未定义的标识符而出错,而不是因为"函数不存在"错误(即使编译器以这种方式报告它(。各种构造函数都是通过重载解析来调用的,所以它们的"存在"是在这方面处理的。
在每种情况下,都有一个通过标识符声明的函数,或者一个构造函数/析构函数(也通过标识符声明,只是一个类型标识符(。运算符重载将标识符隐藏在语法糖后面,但它仍然存在。
C++规范无法处理"不存在的函数"的概念。它可以处理重载不匹配。它可以处理超负荷的模糊性。但它不知道什么是不存在的。因此,= delete
的定义是更有用的"尝试称之为失败",而不是不太有用的"假装我从未写过这行">
再次重读第一部分。不能用"函数不存在"来实现这一点。这也是它被这样定义的另一个原因:因为= delete
语法的主要用例之一是能够强制用户使用某些参数类型、显式强制转换等等。基本上,是为了避免隐式类型转换。
你的建议不会那样做。
2012-11-02 C++工作草案没有提供该规则背后的基本原理,只是的一些例子
8.4.3已删除定义[dcl.fct.def.delete]
…
3[示例:可以使用强制执行非默认初始化和非积分初始化
struct onlydouble {
onlydouble() = delete; // OK, but redundant
onlydouble(std::intmax_t) = delete;
onlydouble(double);
};
--结束示例]
示例:通过使用已删除的类的定义,可以防止在某些新表达式中使用类用户为该类声明了new运算符。
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[]
--结束示例]
示例:通过使用已删除的副本定义,可以使类不可复制,即仅移动构造函数和复制赋值运算符,然后提供move构造函数的默认定义和移动分配运算符。
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
--结束示例]
- 运行同一解决方案的另一个项目的项目
- Project Euler问题4的错误解决方案
- Ardunio UNO解决了多个重叠的定时器循环
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 是否有一个很好的方法可以在C 11中打印出像JSON一样的Trie结构(仅迭代解决方案)的扁平命名空间
- 解决死锁问题,在主线程中等待多个工作线程完成 (C++11)
- C 11魔术静态在Visual Studio 2012中的解决方法
- 我写了一个函数来删除循环链接列表中的第 1 个节点,但输出显示无限次"55 44 33 22 11 99",那么我该如何解决呢?
- C 11:此不完整类型错误的解决方法
- 如何使用 -std=C++11 解决 G++ 警告:“auto_ptr”已弃用
- 在 Solaris 11 上安装 gdb-7.2 以解决分段错误
- c++11 是否提供与 python maketrans/translate 中实现的解决方案类似的解决方案?
- C++11 :从当前实例(此)进行unique_ptr的解决方法
- C++11内存池类-从void*进行static_casting的解决方法
- 宏/内联函数解决MSVC10/11中缺少统一初始化式的问题
- 如何解决 DirectX 11 程序中"unresolved external symbol"错误?
- 如何将c++11导入eclipse neon?我的代码给了我错误,我听说这就是解决方案
- 为什么C++11删除的函数会参与过载解决
- 如何在c++11中将迭代器转换为字符串?boost解决方案也可以
- 破解编码面试的LIS解决方案中的分割故障11.7