简体   繁体   English

如何防止std :: string使用initializer_list构造函数?

[英]How to prevent std::string from using the initializer_list constructor?

I want the following code to output "test" instead of "X" for the case when using std::string using the same initialization as the other basic types. 对于使用std::string且与其他基本类型相同的初始化的情况,我希望以下代码输出“ test”而不是“ X”。 std::string now calls the constructor with an initializer_list and therefore the template specialization of get for char is called. 现在, std::string使用initializer_list调用构造initializer_list ,因此将调用get for 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'
}

Is there a nice way of doing this without breaking the consistent look of the variable initializations? 有没有做到这一点的好方法,而又不会破坏变量初始化的一致外观?

std::string has a constructor that takes an initializer_list<char> argument; std::string有一个带有initializer_list<char>参数的构造函数; that constructor will always be considered first when you use list-initialization with a non-empty braced-init-list, that's why the char specialization of get() is being matched. 当您将列表初始化与非空的花括号初始化列表一起使用时,始终会首先考虑该构造函数,这就是为什么要匹配get()char专业化的原因。

If you use parentheses instead of braces for all the initializations, the initializer_list constructor will no longer be the only one considered in the std::string case. 如果对所有初始化都使用括号而不是括号,则在std::string情况下, initializer_list构造函数将不再是唯一的构造函数。

auto nbr = int( conf["int"] );
auto dbl = double( conf["dbl"] );
auto str = std::string( conf["str"] );

However, this change alone doesn't work because you have an implicit user-defined conversion template that can yield any type. 但是,仅此更改是行不通的,因为您有一个隐式的用户定义的转换模板,该模板可以产生任何类型。 The code above, in the std::string case, results in matches for all std::string constructors that can be called with a single argument. 上面的代码在std::string情况下,导致可以用单个参数调用的所有std::string构造函数都匹配。 To fix this make the conversion operator explicit . 要解决此问题,请使转换运算符explicit

struct proxy {
    // use cool parser to actually read values
    template<typename T>
    explicit operator T(){ return get<T>(); }
};

Now, only the explicit conversion to std::string is viable, and the code works the way you want it to. 现在,只有显式转换为std::string才可行,并且代码按您希望的方式工作。

Live demo 现场演示

auto nbr = (int)conf["int"];
auto dbl = (double)conf["dbl"];
auto str = (string&&)conf["str"];

you have defined template operator T(), the above just calls it. 您已经定义了模板运算符T(),上面的代码只是调用它。 to make a copy, you can 进行复制,您可以

auto str = string((string&&)conf["str"])

EDIT: changed (string) to (string&&) 编辑:将(string)更改为(string &&)

EDIT2: following works as well (tested them all - gcc -std=c++11): EDIT2:以下工作也很好(全部测试了它们-gcc -std = c ++ 11):

auto nbr = (int&&)conf["int"];
auto dbl = (double&&)conf["dbl"];
auto str = (string&&)conf["str"];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 std :: initializer_list构造函数 - std::initializer_list constructor 如何在不使用 std::initializer_list 的情况下定义初始化列表构造函数? - How to define initializer list constructor without using std::initializer_list? 使用 std::initializer_list 时出现分段错误<std::string>在构造函数中</std::string> - Segmentation fault when Using std::initializer_list<std::string> in Constructor std :: initializer_list作为std :: array构造函数 - std::initializer_list as std::array constructor 使用std :: initializer_list构造函数而不会产生歧义? - Using std::initializer_list constructor without creating ambiguities? 如何在ChaiScript中使用用户类型的std :: initializer_list调用构造函数? - How call a constructor with std::initializer_list of a user type in ChaiScript? 如何编写正确的std :: initializer_list构造函数 - How to write proper std::initializer_list constructor 如何使用带有 std::initializer_list 的构造函数设计类? - How to design classes with constructor taking a std::initializer_list? 如何使用 std::initializer_list 创建构造函数<double></double> - How to make a constructor with std::initializer_list<double> 如何构建 std::vector<std::string> 来自 std::initializer_list<char const*> - How to build std::vector<std::string> from std::initializer_list<char const*>
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM