对于使用与其他基本类型相同的初始化的 std::string
的情况,我希望以下代码输出“test”而不是“X”。 std::string
现在调用带有 initializer_list
的构造函数,因此 get
的模板特化为 char
被调用.
#include <sstream>
#include <string>
#include <iostream>
// Imagine this part as some kind of cool parser.
// I've thrown out everything for a simpler demonstration.
template<typename T> T get() {}
template<> int get(){ return 5; }
template<> double get(){ return .5; }
template<> char get(){ return 'X'; }
template<> std::string get(){ return "test"; }
struct Config {
struct proxy {
// use cool parser to actually read values
template<typename T> operator T(){ return get<T>(); }
};
proxy operator[](const std::string &what){ return proxy{}; }
};
int main()
{
auto conf = Config{};
auto nbr = int{ conf["int"] };
auto dbl = double{ conf["dbl"] };
auto str = std::string{ conf["str"] };
std::cout << nbr << std::endl; // 5
std::cout << dbl << std::endl; // 0.5
std::cout << str << std::endl; // 'X'
}
有没有一种很好的方法可以在不破坏变量初始化的一致外观的情况下做到这一点?
最佳答案
std::string
有一个接受 initializer_list<char>
的构造函数争论;当您将列表初始化与非空的花括号初始化列表一起使用时,将始终首先考虑该构造函数,这就是为什么 char
特化get()
正在匹配。
如果您在所有初始化中使用圆括号而不是大括号,则 initializer_list
构造函数将不再是 std::string
中唯一考虑的构造函数案例。
auto nbr = int( conf["int"] );
auto dbl = double( conf["dbl"] );
auto str = std::string( conf["str"] );
但是,仅此更改是行不通的,因为您有一个可以产生任何类型的隐式用户定义转换模板。上面的代码,在 std::string
中案例,结果匹配所有 std::string
可以用单个参数调用的构造函数。要解决此问题,请使用转换运算符 explicit
.
struct proxy {
// use cool parser to actually read values
template<typename T>
explicit operator T(){ return get<T>(); }
};
现在,只有显式转换为 std::string
是可行的,并且代码按照您希望的方式工作。
关于c++ - 如何防止 std::string 使用 initializer_list 构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25021300/