在构造函数中更改函数解析优先级
C++ Change function resolution precedence in constructor
考虑以下代码:
#include <cstdio>
#include <initializer_list>
using namespace std;
class A {
public:
A(const char*, void*) { printf("const char*, void*n"); }; // #1
A(initializer_list<char*>) { printf("initializer_list<char*>n"); }; // #2
};
void F(const A&) {};
int main(int, char**) {
F({ "A", new char[256]() });
};
我有一个函数F
,我可以用is_constructible
到class A
的任何参数调用它。
如果我运行程序,我看到构造函数#2被调用,并且我得到一个类似于第一个参数的警告:ISO C++11 does not allow conversion from string literal to 'char *const'
。c++会自动将此参数从字符串字面值转换为char*
,以便调用匹配签名initializer_list<char*>
。
但是编译器也可以尝试将第二个形参强制转换为void*
,这样调用就可以匹配签名const char*, void*
。
两个调用从调用到"匹配签名"的步骤相同,但由于某种原因编译器选择了后者。
我想了解这种选择背后的基本原理是什么,而且,如果有任何机会"提示"编译器在第一个参数是字符串文字时使用构造函数#1。
纵观全局,
我想调用:F({ "A", new char[256]() })
选择构造器#1,
但是像F({ (char*)"A", new char[256]() })
这样的调用选择构造器#2。
编译器的细节:Apple LLVM 6.0版本(clang-600.0.57)(基于LLVM 3.5svn)目标:x86_64-apple-darwin14.1.0线程模型:posix
像#2这样的初始化列表构造函数优先于其他构造函数。只要它是一个可行的构造函数,那么它们就会被考虑,尽管可能存在更可行的非初始化列表构造函数。字符串字面值是一个N const char
数组,从字符串字面值到char*
的转换作为C的遗留,但自c++ 03以来已被弃用。
由于转换无论如何都可能发生,因此仍然使用构造函数而不是#1。可以通过将其转换为非文字(即从函数返回)来防止这种转换:
const char* operator"" _strong(const char* str, std::size_t) {
return str;
}
int main() {
F({ "A", new char[256]() }); // #1
F({ "A"_strong, new char[256]() }); // #2
}
现在到char*
的转换将失败,重载解析将考虑#1作为候选构造函数
- 优先级队列构造函数的工作
- C++ 带有函数指针的运算符优先级
- 赋予全局变量而不是局部变量优先级的函数 - (异常行为)
- 具有值包装器的可变参数模板构造函数的类构造函数优先级
- 排序函数和优先级队列 C++ 中的比较器
- 如何在 c++ 中的函数参数中声明优先级队列
- 交换优先级队列时尝试引用已删除的函数错误
- 类构造函数比"="运算符具有更高的优先级?
- 选择用于赋值初始化的转换函数的优先级
- C++默认参数构造函数与内联初始化优先级
- C++ 具有自定义比较函数的优先级队列在 push() 上行为不正确
- 函数重载优先级(引用)
- 模板类根据其他类的存在性和优先级以及更多的类型限制(如常量和区分大小写)调用其他类的某些函数
- C 优先级队列构造函数
- 谁可以解释更多关于优先级队列C++中的比较函数
- 函数重载和模板扣除优先级
- 运算符重载,成员函数和非成员函数,哪一个具有优先级
- stl 优先级队列中的堆管理是否调用复制构造函数
- 优先级队列中复制构造函数覆盖的值
- 优先级队列成员函数不起作用