9

コンパイル時に文字列の配列を作成する簡単な方法を探しています。Stringsテストのために、次のメンバーを持つという名前のクラスをまとめました。

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&から、operator,for を呼び出す getを呼び出します"World!"

私がうまくいかないのは(MSVCでは、まだ他のコンパイラを試していません)

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

Strings s="Hello"ここでは、コピー コンストラクターが呼び出され、すべてが最初の例と同じように動作すると仮定します。しかし、私はエラーが発生します:error C2059: syntax error : 'string'

ただし、これは正常に機能します。

Strings s="Hello"; 

したがって、コピー コンストラクターが少なくとも 1 つの文字列に対して機能することはわかっています。何か案は?コードをもう少しきれいにするために、2番目の方法を機能させたいと思います。

4

7 に答える 7

14

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

たとえば、次のように書くことができます。

int a=3, b=4

あなたが本質的に書いているように私には思えます:

Strings s="Hello", stringliteral

そのため、コンパイラはコンマの後の項目が変数の名前であると想定し、代わりに文字列リテラルを確認してエラーを通知します。つまり、コンストラクターは「Hello」に適用されますが、その後のコンマは Strings のコンマ演算子ではありません。

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

于 2009-10-12T22:29:59.577 に答える
8

この種の API はお勧めしません。コンマは優先順位が最も低い演算子であるため、期待どおりに機能しないケースを引き続き発見することになります。たとえば、次のケースも機能しません。

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

次のように、文字列のセットを毎回括弧で囲むと、うまくいく場合があります。

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

上記の例は次のようになります。

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

それはうまくいく可能性がありますが、簡略化された構文は、それに付随するトリッキーなセマンティクスに値するものではありません。

于 2009-10-12T22:34:56.353 に答える
5

を使用しboost::list_ofます。

于 2009-10-12T22:32:07.533 に答える
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;
}
于 2009-10-12T23:24:16.770 に答える
0

文字ポインタの配列を使用できます

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

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

Strings s(input);

コンストラクター内で、null に到達するまでポインターを反復処理します。

于 2009-10-12T22:37:23.863 に答える
0

あなたが c++0x なら、彼らはこれのための新しい初期化リストを持っています! そちらをご利用いただければと思います。例えば:

std::vector<std::string> v = { "xyzzy", "plugh", "abracadabra" };
std::vector<std::string> v{ "xyzzy", "plugh", "abracadabra" };
于 2009-10-12T22:39:08.200 に答える
0

の唯一の仕事がStrings文字列のリストを保存することである場合、boost::assign標準のコンテナを使用するとよりうまく仕事ができると思います:)

using namespace boost::assign;
vector<string> listOfThings;
listOfThings += "Hello", "World!";
于 2009-10-12T22:46:35.963 に答える