C++ 使用逗号运算符编译变量初始化失败

C++ 使用逗号运算符编译变量初始化失败,c++,variable-initialization,C++,Variable Initialization,为什么以下代码中指示的行(在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 &l

为什么以下代码中指示的行(在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;
}
#包括
#包括
#包括
模板struct清单:public std::map<\u T,int>
{
布尔盖塔特(内部i、U T&T、内部n)
{
if((i<0)|(i>=(int)this->size())返回false;
int c=0;
typename std::map<\T,int>::迭代器it=this->begin();
((c<i)& &(t!-> ->())){C++,i++;}
t=(*it)。首先;
n=(*it)。第二;
返回true;
}
Inventory&operator=(T T){(*this)[T]+;return*this;}
库存与运算符,(_T){返回运算符=(T);}
};
int main()
{
int i=0,数量;
std::字符串项;
//***未能编译:***
//存货inv=“a”、“b”、“c”、“a”、“c”、“d”、“e”;
库存<标准::字符串>库存;
inv=“a”、“b”、“c”、“a”、“c”、“d”、“e”;//但这很好
inv=“e”,“f”;
而(i<(int)存货大小()
{
if(存货获取(一、项目、数量))

std::cout这称为复制初始化。简而言之,它使用转换构造函数,然后使用复制构造函数来构造
inv
,而不是像您期望的那样使用
操作符=

Inventory< std::string > inv = "a","b","c","a","c","d","e";  
调用默认构造函数,然后

inv = "a","b","c","a","c","d","e"; 

对已初始化的对象调用
运算符=

这称为复制初始化。简而言之,它使用转换构造函数,然后使用复制构造函数来构造
inv
,而不是像您预期的那样使用
运算符=

Inventory< std::string > inv = "a","b","c","a","c","d","e";  
调用默认构造函数,然后

inv = "a","b","c","a","c","d","e"; 

对已初始化的对象调用
运算符=

问题在于,在一种情况下,逗号是标点符号(和 运算符重载不适用),而在另一种情况下,它是 运算符。不起作用的定义基本上是等价的 其中:

您还可以重载运算符并使用它,而不是函数
add
。但是我没有看到一个可能的运算符(
),你的问题是,在一个例子中,逗号是标点符号(和
运算符重载不适用),而在另一种情况下,它是
运算符。不起作用的定义基本上是等价的
其中:

您还可以重载运算符并使用它,而不是函数
add
。但是我没有看到一个可能的运算符(
是否可以创建一个可以处理这样一个随机大小的列表的构造函数?(我正在玩弄逗号运算符,以了解它可以做什么和不能做什么,以及它在哪里有用。)您的解释是错误的。在这种情况下,逗号根本不是运算符,而是分隔符:
Inventory inv=“a”、“b”
Inventory inv=“a”Inventory“b”相同
而且编译器不喜欢变量名是字符串常量。@JamesKanze虽然这是真的,但我看不出解释有什么错。@slashmais逗号运算符重载唯一能做的事情就是混淆。重载运算符的行为应该与内置运算符相对应。这意味着t您不应该重载创建序列点的运算符。(重载
&&
|
也是一个坏主意。)在逗号的情况下,还有一个问题,有时是运算符,有时是标点符号,重载只适用于运算符。@LuchianGrigore您说编译器会首先尝试从
“a”、“b”、“c”、“a”、“c”、“d”、“e”创建一个临时
清单
。这是错误的:它将尝试从
“a”
创建一个临时变量,然后定义一个名为
“b”
(这当然是非法的,因为字符串文字不能作为变量的名称)。是否可以创建一个构造函数来处理这样一个随机大小的列表?(我正在玩弄逗号运算符,以了解它能做什么和不能做什么,以及在哪里有用。)您的解释是错误的。在这种情况下,逗号根本不是运算符,而是分隔符:
Inventory inv=“a”,“b”
Inventory inv=“a”Inventory“b”相同
而且编译器不喜欢变量名是字符串常量。@JamesKanze虽然这是真的,但我看不出解释有什么错。@slashmais逗号运算符重载唯一能做的事情就是混淆。重载运算符的行为应该与内置运算符相对应。这意味着t您不应该重载创建序列点的运算符。(重载
&&
|
也是一个坏主意。)在逗号的情况下,还有一个问题,有时是运算符,有时是标点符号,重载只适用于运算符。@LuchianGrigore您说编译器会首先尝试从
“a”、“b”、“c”、“a”、“c”、“d”、“e”创建一个临时
清单
。这是错误的:它将尝试从
“a”
创建一个临时变量,然后定义一个名为
“b”
(这当然是非法的,因为字符串文字不能作为变量的名称)。如果您的编译器支持
#include
,那么您可以使用
库存库存存货{“a”、“b”、“c”、“a”、“c”、“d”、“e”};
。请参阅VS2012(不支持).@rubberboots:我在使用gcc;将您的建议与
收集器结合起来
-詹姆斯·坎兹的答案中的想法可能会很有用。@slashmais-您不需要两者。如果您将使用的编译器都支持初始值设定项列表,那就是最好的选择。如果不支持,请使用
收集器
的想法。如果您的编译器支持
,请包含
yo你可以使用
库存库存库存{“a”、“b”、“c”、“a”、“c”、“d”、“e”};
。请参阅VS2012(不支持)。@rubberboots:我使用的是gcc;将你的建议与
收集器相结合
-James Kanze回答中的想法可能很有用。@slashmais-你不需要两者兼而有之
Inventory<std::string> inv = Collector().add("a").add("b")...;
Inventory<std::string> inv = Collector("a")("b")...;