2009-10-12 7 views
9

私は、コンパイル時に文字列の配列を作成する簡単な方法を探しています。 、私は正常にこのようなコードをコンパイルすることができ、これを使用してコンマ演算子の乱用

Strings(); 
Strings(const Strings& that); 
Strings(const char* s1); 
Strings& operator=(const char* s1); 
Strings& operator,(const char* s2); 

Strings s; 
s="Hello","World!"; 

s="Hello"一部を返しoperator=を呼び出してテストするために、私は、以下のメンバーを持っているStringsをという名前のクラスをまとめますa Strings&、次にoperator,"World!"と呼ばれます。私は(まだ他のコンパイラを試していませんが、MSVCで)動作させることはできませんどのような

Strings s="Hello","World!"; 

である私はStrings s="Hello"は、コピーコンストラクタを呼び出すと、その後すべてが振る舞うであろうと、ここで想定したいです最初の例と同じです。しかし、私はエラーを取得する:error C2059: syntax error : 'string'

しかし、これは正常に動作します:

Strings s="Hello"; 

は、だから私は、コピーコンストラクタは、1つの文字列のため、少なくとも作業を行うことを知っています。何か案は?私は実際にコードを少しきれいにするために2番目の方法を働かせたいと思っています。

+8

うわー、コンマ演算子のオーバーロードについてたくさんのジョークを聞いたことがあります。私は誰かが実際にそれを** **行うことは決してなかった。 –

+2

@Carl:http://www.boost.org/doc/libs/1_40_0/libs/assign/doc/index.html#introについて(非常にOPが望んでいるものに似ています) – UncleBens

+0

* shudder *自分でパットする棺。間違って始めるとどうやってこれをデバッグするのですか? –

答えて

14

私は、2番目の例のカンマはカンマ演算子ではなく、複数の変数宣言の文法要素であると思います。

例えば、あなたが書くことができるのと同じ方法:

int a=3, b=4 

あなたが、本質的に書いているように私には思える:だからコンパイラは、コンマの後に項目があることを想定してい

Strings s="Hello", stringliteral 

代わりに文字列リテラルが表示され、エラーが通知されます。つまり、コンストラクタは "Hello"に適用されますが、その後のコンマはではなく、のStringのカンマ演算子です。

ところで、コンストラクタは実際にはコピーコンストラクタではありません。リテラル文字列パラメータからStringsオブジェクトを作成します...コピーコンストラクタという用語は、通常、同じ型に適用されます。

+2

'' String s = "Hello"; 'は' 'Strings = Strings(" Hello ");'と同じです。コピーctorを呼び出し可能にする必要があり、一時オブジェクトから 's'を構築するために呼び出すことさえあります。しかし、 's'の' const char * 'コンストラクタを直接初期化せずに置き換える最適化は、一時的なものではなく、一般的なものです。 –

+0

私はそれを見なかったと信じられない。 – miked

8

この種のAPIはお勧めできません。コンマは優先順位が最も低い演算子なので、期待どおりに動作しないケースを引き続き検出します。たとえば、この場合はどちらか動作しません。

if ("Hello","world" == otherStrings) { ... } 

あなたは文字列のセットの周りたびにブラケットを使用する場合は、このように、作業のものを得ることができるかもしれません:

Strings s=("Hello","World!"); 

そして、私の上記の例は次のようになります。

可能性の高い動作させることができ
if (("Hello","world") == otherStrings) { ... } 

が、速記構文は、おそらくそれが付属していますトリッキーなセマンティクス価値はありません。

+3

それは働くことができますか?私が予期する問題は、 'const char *'の '演算子'をオーバーロードできないので、 '(" Hello "、" world ")'は '' world "'とまったく同じです。 –

+0

私は、演算子(const char *、const char *)をオーバーロードできると仮定しました。それができない理由がありますか?私は多くのC++プログラミングを正直にしていません。 –

0

あなたはヌルを打つまでのポインタを反復処理、文字ポインタ

Strings::Strings(const char* input[]); 

const char* input[] = { 
    "string one", 
    "string two", 
    0}; 

Strings s(input); 

とコンストラクタの内部の配列を使用することができます。

+0

また、コンストラクタをテンプレートします。テンプレート文字列(const char *(&input)[N]){for(int i = 0; i

+0

ああ、もちろん、コンストラクタテンプレートは 'vector :: insert(iterator、InputIterator、InputIterator)'のような別の関数を呼び出すことができます。 –

0

C++ 0xの場合、これは新しいinializer listsです!私はあなたがそれらを使うことができたらいいと思う。たとえば:Stringsの唯一の仕事は、文字列のリストを格納する場合

std::vector<std::string> v = { "xyzzy", "plugh", "abracadabra" }; 
std::vector<std::string> v{ "xyzzy", "plugh", "abracadabra" }; 
0

、その後、boost::assignは、私はそれを行うことが可能です:)

using namespace boost::assign; 
vector<string> listOfThings; 
listOfThings += "Hello", "World!"; 
1

を考えて、標準コンテナとのより良い仕事をすることができこの作品は、「仕事」を十分に緩やかに定義しています。ここ数年前に私が似たような質問に答えて書いた実例があります。それは面白いことでしたが、私は実際のコードでそれを使用しませんでした。

#include <iostream> 
#include <algorithm> 
#include <iterator> 
#include <vector> 

void f0(std::vector<int> const &v) { 
    std::copy(v.begin(), v.end(), 
     std::ostream_iterator<int>(std::cout, "\t")); 
    std::cout << "\n"; 
} 

template<class T> 
class make_vector { 
    std::vector<T> data; 
public: 
    make_vector(T const &val) { 
     data.push_back(val); 
    } 

    make_vector<T> &operator,(T const &t) { 
     data.push_back(t); 
     return *this; 
    } 

    operator std::vector<T>() { return data; } 
}; 

template<class T> 
make_vector<T> makeVect(T const &t) { 
    return make_vector<T>(t); 
} 

int main() { 
    f0((makeVect(1), 2, 3, 4, 5)); 
    f0((makeVect(1), 2, 3)); 
    return 0; 
}