这里以一个类定义为例。
#include <string>
#include <map>
template <class T>
class Collection
{
private:
std::map<std::string, T> data;
public:
Collection() {}
Collection(std::map<std::string, T> d)
{
data = d;
}
};
使用int
s,char
s甚至vector
模板类型初始化Collections时,此方法都可以正常工作。但是,当使用a初始化一个string
并调用第二个重载的构造函数时,例如:
Collection<std::string> col({
{ "key", "value" }
});
它不会编译,并引发以下退出错误:
main.cpp:24:22: error: call to constructor of 'Collection<std::__cxx11::string>'
(aka 'Collection<basic_string<char> >') is ambiguous
Collection<string> col({
^ ~
main.cpp:8:7: note: candidate constructor (the implicit move constructor)
class Collection
^
main.cpp:8:7: note: candidate constructor (the implicit copy constructor)
main.cpp:16:3: note: candidate constructor
Collection(map<string, T> d)
^
奇怪的是,虽然这种表示法可以与其他类型配合使用,并且可以中断,但这种表示法适用于string
:
Collection<std::string> col(std::map<std::string, std::string>({
{ "key", "value" }
}));
这里发生了什么?
这是一个有趣的。
map
可以从两个迭代器构造A :
template<class InputIterator>
map(InputIterator first, InputIterator last,
const Compare& comp = Compare(), const Allocator& = Allocator());
值得注意的是,根本不需要此构造函数检查是否InputIterator
是迭代器,更不用说将其取消引用的结果可转换为map
的value类型了。当然,实际上尝试构造映射将失败,但是可以map
通过相同类型的任何两个参数来构造重载解析。
所以用
Collection<std::string> col({
{ "key", "value" }
});
编译器有两种解释:
map
使用map
的initializer-list构造函数初始化a,内部花括号pair
为该initializer-list构造函数初始化a 。Collection
,内花括号map
使用“ iterator-pair”构造函数初始化a 。两者都是排名中用户定义的转换,两者之间没有决胜局,因此调用是不明确的-即使第二个调用(如果选择)也会在map
构造函数内部导致错误。
在最外层也使用花括号时:
Collection<std::string> col{{
{ "key", "value" }
}};
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句