为什么以下代码中的行(在main()中)不能编译?
#include <iostream>
#include <string>
#include <map>
template< typename _T > struct Inventory : public std::map< _T, int >
{
bool getat(int i, _T &t, int &n)
{
if ((i < 0) || (i >= (int)this->size())) return false;
int c=0;
typename std::map< _T, int >::iterator it = this->begin();
while ((c < i) && (it != this->end())) { c++; it++; }
t = (*it).first;
n = (*it).second;
return true;
}
Inventory &operator=(_T t) { (*this)[t]++; return *this; }
Inventory &operator,(_T t) { return operator=(t); }
};
int main()
{
int i=0, quantity;
std::string item;
//***Fails to compile:***
//Inventory< std::string > inv = "a","b","c","a","c","d","e";
Inventory< std::string > inv;
inv = "a","b","c","a","c","d","e"; //but this is fine
inv = "e","f";
while (i < (int)inv.size())
{
if (inv.getat(i, item, quantity))
std::cout << i << ": " << item << " -> " << quantity << "\n";
i++;
}
return 0;
}
答案 0 :(得分:2)
这称为复制初始化。简而言之,它使用转换构造函数,然后使用复制构造函数构建inv
,而不是operator =
。
Inventory< std::string > inv = "a","b","c","a","c","d","e";
语法无效。像Inventory< std::string > inv = "a"
这样的东西会首先尝试从Inventory
创建一个临时"a","b","c","a","c","d","e"
,然后将该临时用作复制构造函数的参数来构造inv
。在这种情况下永远不会调用operator =
。
您的第二个版本有效,因为
Inventory< std::string > inv;
调用默认构造函数和
inv = "a","b","c","a","c","d","e";
在已初始化的对象上调用operator =
。
答案 1 :(得分:2)
你的问题是,在一个案例中,逗号是标点符号(和 运算符重载不适用),另一方面,它是一个 运营商。不起作用的定义基本上是等效的 的:
Inventory<std::string> inv = "a";
Inventory<std::string> "b";
Inventory<std::string> "c";
// ...
因此,重载operator,
总是糟糕的设计;当。。。的时候
逗号是一个操作符,如果不是,则太过微妙。
通常这样做的方法是创建一个相关的类 收集参数,并将其传递给构造函数:
Inventory<std::string> inv = Collector().add("a").add("b")...;
您也可以重载操作符并使用它,而不是函数
add
。但我没有看到可能的运算符(<<
,受ostream
的启发?)
或者你可以重载构造函数和operator()
Collector
,并写下:
Inventory<std::string> inv = Collector("a")("b")...;
然后,您将使用相同的语法进行分配。 (你真的没有 想要一些适合作业的东西,而不是复制品 结构。)