如何解决采用 std::string 和 std::vector 的构造函数之间的歧义
How to resolve ambiguity between constructors taking std::string and std::vector
我想制作一个 "Tag" class 可以将其名称指定为点分隔名称,如 "this.is.my.name"
或字符串向量,如 {"this","is","my","name"}
.
当我尝试这样做时,有时 编译器告诉我我的调用不明确。我想知道 (1) 为什么这根本不明确,以及 (2) 为什么它只是有时不明确。
这是我的示例代码,您也可以查看和编译here on Coliru
#include <string>
#include <vector>
#include <iostream>
class Tag
{
public:
explicit Tag(std::string name);
explicit Tag(std::vector<std::string> name);
};
Tag::Tag(std::string name)
{
//here 'name' will be a dotted collection of strings, like "a.b.c"
}
Tag::Tag(std::vector<std::string> name)
{
//here 'name' will be a vector of strings, like {"a","b","c"}
}
int main(int argc, char**argv)
{
Tag imaTag{{"dotted","string","again"}};
Tag imaTagToo{"dotted.string"};
//everything is fine without this line:
Tag imaTagAlso{{"dotted","string"}};
std::cout << "I made two tags" << std::endl;
}
在指示的行中,出现以下错误:
g++ -std=c++11 -O2 -Wall -pthread main.cpp && ./a.out
main.cpp: In function 'int main(int, char**)':
main.cpp:28:39: error: call of overloaded 'Tag(<brace-enclosed initializer list>)' is ambiguous
Tag imaTagAlso{{"dotted","string"}};
^
main.cpp:18:1: note: candidate: 'Tag::Tag(std::vector<std::__cxx11::basic_string<char> >)'
Tag::Tag(std::vector<std::string> name)
^~~
main.cpp:13:1: note: candidate: 'Tag::Tag(std::__cxx11::string)'
Tag::Tag(std::string name)
^~~
Tag imaTagAlso{{"dotted","string"}};
表示构造一个Tag
,调用它imaTagAlso
并用{"dotted","string"}
初始化它。问题是 std::string
可以由一对迭代器构造,并且由于字符串文字可以衰减为 const char*
,因此它们有资格作为迭代器。因此,您可以使用 "iterators" 调用字符串构造函数,也可以使用其 std::initializer_list
构造函数调用向量构造函数。要解决此问题,您可以使用
Tag imaTagAlso{{{"dotted"},{"string"}}};
表示构造一个 Tag
,将其命名为 imaTagAlso
并用 {{"dotted"},{"string"}}
初始化它,现在 {"dotted"}
和 {"string"}
成为 [= 的元素18=] 用于向量构造函数。
你也可以(自 c++14 起)像
那样使用 std::string
's user defined literal operator (""s
)
Tag imaTagAlso{{"dotted"s,"string"s}};
这使得 braced-init-list std::string
的每个元素,向量构造函数将被选择。
我想制作一个 "Tag" class 可以将其名称指定为点分隔名称,如 "this.is.my.name"
或字符串向量,如 {"this","is","my","name"}
.
当我尝试这样做时,有时 编译器告诉我我的调用不明确。我想知道 (1) 为什么这根本不明确,以及 (2) 为什么它只是有时不明确。
这是我的示例代码,您也可以查看和编译here on Coliru
#include <string>
#include <vector>
#include <iostream>
class Tag
{
public:
explicit Tag(std::string name);
explicit Tag(std::vector<std::string> name);
};
Tag::Tag(std::string name)
{
//here 'name' will be a dotted collection of strings, like "a.b.c"
}
Tag::Tag(std::vector<std::string> name)
{
//here 'name' will be a vector of strings, like {"a","b","c"}
}
int main(int argc, char**argv)
{
Tag imaTag{{"dotted","string","again"}};
Tag imaTagToo{"dotted.string"};
//everything is fine without this line:
Tag imaTagAlso{{"dotted","string"}};
std::cout << "I made two tags" << std::endl;
}
在指示的行中,出现以下错误:
g++ -std=c++11 -O2 -Wall -pthread main.cpp && ./a.out
main.cpp: In function 'int main(int, char**)':
main.cpp:28:39: error: call of overloaded 'Tag(<brace-enclosed initializer list>)' is ambiguous
Tag imaTagAlso{{"dotted","string"}};
^
main.cpp:18:1: note: candidate: 'Tag::Tag(std::vector<std::__cxx11::basic_string<char> >)'
Tag::Tag(std::vector<std::string> name)
^~~
main.cpp:13:1: note: candidate: 'Tag::Tag(std::__cxx11::string)'
Tag::Tag(std::string name)
^~~
Tag imaTagAlso{{"dotted","string"}};
表示构造一个Tag
,调用它imaTagAlso
并用{"dotted","string"}
初始化它。问题是 std::string
可以由一对迭代器构造,并且由于字符串文字可以衰减为 const char*
,因此它们有资格作为迭代器。因此,您可以使用 "iterators" 调用字符串构造函数,也可以使用其 std::initializer_list
构造函数调用向量构造函数。要解决此问题,您可以使用
Tag imaTagAlso{{{"dotted"},{"string"}}};
表示构造一个 Tag
,将其命名为 imaTagAlso
并用 {{"dotted"},{"string"}}
初始化它,现在 {"dotted"}
和 {"string"}
成为 [= 的元素18=] 用于向量构造函数。
你也可以(自 c++14 起)像
那样使用std::string
's user defined literal operator (""s
)
Tag imaTagAlso{{"dotted"s,"string"s}};
这使得 braced-init-list std::string
的每个元素,向量构造函数将被选择。