1

次のコードで示されている行 ( 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;
}
4

2 に答える 2

2

問題は、ある場合にはコンマが句読点であり (演算子のオーバーロードは適用されない)、別の場合には演算子であるということです。機能しない定義は、基本的に次のものと同等です。

Inventory<std::string> inv = "a";
Inventory<std::string> "b";
Inventory<std::string> "c";
//  ...

このため、過負荷operator,は常に悪い設計です。コンマが演算子である場合とそうでない場合は微妙すぎます。

このようなことを行う通常の方法は、関連するクラスを作成して引数を収集し、それをコンストラクターに渡すことです。

Inventory<std::string> inv = Collector().add("a").add("b")...;

function の代わりに、演算子をオーバーロードして使用することもできます add。しかし、可能性のある演算子 ( <<、に触発されたostream?) が表示されないか、コンストラクターとoperator()of を オーバーロードして、次のCollectorように記述できます。

Inventory<std::string> inv = Collector("a")("b")...;

次に、割り当てに同じ構文を使用します。(コピーの作成ではなく、代入で機能するものは本当に必要ありません。)

于 2012-10-10T11:28:09.107 に答える
2

これは、コピー初期化と呼ばれます。つまり、変換コンストラクターを使用してから、コピー コンストラクターを使用して を構築しますが、期待どおりinvではありませんoperator =

Inventory< std::string > inv = "a","b","c","a","c","d","e";  

は無効な構文です。のようなものは、最初に一時的なfromInventory< std::string > inv = "a"を作成しようとし、次にその一時的なものをコピー コンストラクターへの引数として使用して construct します。この場合、呼び出されることはありません。Inventory"a","b","c","a","c","d","e"invoperator =

2番目のバージョンが機能する理由

Inventory< std::string > inv;

デフォルトのコンストラクターを呼び出し、

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

operator =すでに初期化されているオブジェクトを呼び出します。

于 2012-10-10T10:49:35.583 に答える