【发布时间】:2015-10-07 15:55:23
【问题描述】:
考虑以下代码:
#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
【问题讨论】:
-
谢谢,我看到了另一个答案,正如预期的 initializer_list 优先于常规签名,但是如何解决我的特定问题?
-
我正在重新打开我自己的 close-as-duplicate。 “为什么”在Why is initializer_list constructor preferred here? 得到了完整的回答,但这个问题并没有解决如果有机会解决这个问题。
-
有趣的是,
initializer_list构造函数甚至不应该是可行的,因为将字符串文字绑定到char*已在 C++11 标准中删除。编译器的行为不合规。 -
归结为,你将如何制作一个只接受 char* 作为参数的 initializer_list
? -
@dyp Atm 它只是抛出一个警告,也许在 C++14 中它会被真正禁用。
标签: c++ c++11 constructor initializer-list