質問

プログラムの実行時にベクトルのタイプを設定する必要があるプログラムがあります(構成ファイルの値に従って)。

これを試しました:

int a = 1

if(a == 1)  vector<int> test(6);
else  vector<unsigned int> test(6);

test.push_back(3);

しかし、これは私に与えます:

Error   1   error C2065: 'test' : undeclared identifier

理由は完全にはわかりませんが、これはコンパイル時にベクトルが実際に決定されないため、コンパイラが残りのコードをコンパイルしている間はベクトルを操作できないためだと思います。

上記で試みたのと同様に、実行時にベクターのタイプを決定する方法はありますか? ifの外側に1つのバージョンを作成してから削除し、IF内で新しいバージョンを書き直そうとしました。しかし、これは間違っていると感じており、とにかく動作させることができません。 ありがとう。

役に立ちましたか?

解決

機能しない理由は、ifブロックとelseブロック内のベクトルをそれぞれ宣言しているため、そのブロックが終了すると範囲外になるためです。

  

上記で試みたのと同様に、実行時にベクターのタイプを決定する方法はありますか?

いいえ、変数の型はコンパイル時にわかっている必要があります。唯一のオプションは、行test.push_back(3)に加えて、testにアクセスする次のコードをif-およびelse-blockに入れるか、コードの重複を2番目のテンプレート関数に回避することです。これは次のようになります。

template <class T>
do_something_with_test(vector<T>& test) {
    test.push_back(3);
    // work with test
}

void foo() {
    int a = 1

    if(a == 1) {
        vector<int> test(6);
        do_something_with_test(test);
    }
    else {
        vector<unsigned int> test(6);
        do_something_with_test(test);
    }
}

他のヒント

発生しているエラーの正確な理由は、初心者にとっては微妙なものであり、作成している変数testのスコープに関係しています。簡単に言えば、ifステートメント内でベクターを作成していますが、使用するときまでに、ベクターが範囲外になったため、もはや存在しません。

この効果をより顕著にするために、コードを括弧で再フォーマットしました。私のバージョンはあなたのものと意味的に同等であり、同じエラーが発生することに注意してください。

if(a == 1)
{
  vector<int> test(6);
}
else
{
  vector<unsigned int> test(6);
}

test.push_back(3);

そうは言っても、あなたがやろうとしていることは少し奇妙に思えます。それはあなたがやりたいと思うことをする方法がないということではありませんが、より適切な方法を提案する前にあなたの成功基準を知る必要があります。

なぜそれが必要なのかわかりませんが、ユニオンのベクトルを使用して問題を解決することをお勧めします。次のようなものです

union DataType
{
    int intVal;
    unsigned uintVal;
}
std::vector<DataType> vec;

またはおそらくもっとエレガントな方法は、 boost ::を使用することです。ユニオンではなくバリアント。問題の詳細をお知らせいただければ、より良い回答が得られるでしょう。

がんばって!

boost :: any 同様のことを実現します。

ベクターのタイプ(テンプレートのインスタンス化)の設定は、常にコンパイル時に行われます。詳細については、テンプレートメタプログラミングに関するウィキペディアの記事をご覧ください。

多相型が本当に必要な場合は、おそらくboost :: variantクラスまたは類似のものを見てみましょう。
これは、C ++内の動的言語の動作の一部を模倣するように設計されており、通常、動的言語とのインターフェース(または実装)に使用されます。 <!> quot; vector <!> lt;を作成できます。バリアント<!> gt; a <!> quot ;、およびa.push_back(Variant((unsigned int)..)。プッシュされる値のコンストラクターには、コンパイル時の型が必要です。

値が同種であると予想される場合、コレクション全体の型情報を格納するベクトル化されたバリアントクラスを作成することも可能です。

しかし、そのようなメカニズムなしで目的の最終結果を達成できる可能性がはるかに高く、おそらくランタイム型チェックを回避するためにプログラムを作り直します(最初の段階で他の言語よりもC ++を使用する利点のいくつかを無効にする可能性が高いです) )。

タイプに依存する部分をテンプレートとして記述し(上記を参照)、構成ファイルの設定に基づいて代替コードパスを選択できます<!> amp;一度派遣。このスタイルのコーディングは、「auto」とdecltype()を使用したc ++ 0xでも少し簡単になります。

符号なしの値と符号付きの値の特定のケースでは、異常に聞こえるビットを追加するか、追加された複雑さに比べてわずかな利点がありますが、単精度と倍精度の浮動小数点数を切り替えることができる実装が必要な人は簡単に想像できます。

さらに別の簡単なオプションは、型のコンパイル時の設定を行い(ビルド設定またはメイクファイルから定義として導入されるなど)、プログラムの複数のバージョンを配布することです。これは状況によっては意味があります。ただし、すでに提案されているテンプレートは、最も有用なオプションである可能性が高くなります。

この例では、testステートメントの各ブランチで作成された変数ifの独立したインスタンスがあり、各インスタンスはすぐに範囲外になります。コンパイラがtest.push_back(3);に到達すると、スコープ内にint変数がないため、エラーが発生します。

問題に対処するために、型システムと戦うことはできません:unsigned intvector<int>が問題の実際の型であると仮定すると、全体を通して<=>を使用する方がはるかに良いでしょう。実際には、符号なし整数の全範囲が必要です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top