0

我想创建一个“标签”类,它的名称可以指定为点分隔名称,也可以指定为"this.is.my.name"字符串向量,例如{"this","is","my","name"}.

当我尝试这样做时,有时编译器会告诉我我的调用是模棱两可的。我想知道(1)为什么这是模棱两可的,以及(2)为什么有时只是模棱两可。

这是我的示例代码,您也可以在 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)
 ^~~
4

1 回答 1

9

Tag imaTagAlso{{"dotted","string"}}; 说构造 a Tag,调用它imaTagAlso并用 初始化它{"dotted","string"}。问题在于std::string可以由一对迭代器构建,并且由于字符串文字可以衰减为const char*'s,因此它们有资格作为迭代器。因此,您可以使用“迭代器”调用字符串构造函数,也可以使用其std::initializer_list构造函数调用向量构造函数。要解决此问题,您可以使用

Tag imaTagAlso{{{"dotted"},{"string"}}};

它说构造 a Tag,调用它并用and 现在imaTagAlso初始化它,并成为向量构造函数的元素。 {{"dotted"},{"string"}}{"dotted"}{"string"}std::initializer_list

您还可以(自 c++14 起)使用std::string用户定义的文字运算符 ( ""s),例如

Tag imaTagAlso{{"dotted"s,"string"s}};

这使得括号初始化列表 std::string的每个元素,并且将选择向量构造函数。

于 2018-12-13T16:38:24.140 回答