消除std :: vector <std :: string>的列表初始化的歧义

Ros*_*oss 5 c++ string stdvector ambiguous-call c++11

我的代码中有一个带有类型签名的重载函数:

void foo(std::string);
void foo(std::vector<std::string>);
Run Code Online (Sandbox Code Playgroud)

我希望foo的用户能够使用字符串或字符串列表来调用它

//Use case 1
foo("str");

//Use case 2
foo({"str1","str2","str3"});
foo({"str1","str2","str3","str4"});
Run Code Online (Sandbox Code Playgroud)

问题是当调用者将两个字符串传递给foo的初始值设定项列表时。

//Problem!
foo({"str1","str2"});
Run Code Online (Sandbox Code Playgroud)

对foo的调用是不明确的,因为它匹配两个类型签名。这是因为显然{"str1","str2"}是有效的构造函数std::string

所以我的问题是,在foo的声明或实现中我可以做些什么,以使我维护上面描述的API而不遇到这种模棱两可的构造方法。

我不想定义自己的字符串类,但是可以定义其他东西,而不必定义其他东西,vector<string>只要它可以使用字符串的初始化列表进行初始化即可。

只是出于好奇,为什么字符串构造函数会接受{"str1","str2"}

Fra*_*eux 5

{"str1","str2"}匹配std::string接受两个迭代器的构造函数。构造函数6 在这里。它将尝试从“ str1”的开头迭代到“ str2”的开头之前,这是未定义的行为。

您可以通过引入重载来解决这种歧义,为此std::initializer_list<const char*>它可以转发给std::vector<std::string>重载。

void foo(std::string);
void foo(std::vector<std::string>);

void foo(std::initializer_list<const char*> p_list)
{
    foo(std::vector<std::string>(p_list.begin(), p_list.end()));
}
Run Code Online (Sandbox Code Playgroud)