8

vector<T>は、ベクトルの大きさを取るコンストラクタを持っており、私の知る限りでは、それは私がすることはできませんintからvectorへの暗黙的な変換?

void f(std::vector<int> v); 
int main() 
{ 
    f(5); 
} 

をコンパイルするには、次のコードが失敗したという事実によって証明することができ明示、あります理解し、説明するために、あなたを求めていますが、次のコードは、

std::vector<std::vector<int>> graph(5, 5); 

ないだけをコンパイルし、なぜそれがコンパイルんですが、それは実際には5にグラフのサイズを変更し、5ゼロのベクトルに各要素を設定し、つまりは同じように同じことを行いますコード私は通常書く:

std::vector<std::vector<int>> graph(5, std::vector<int>(5)); 

どのようにですか?どうして?

コンパイラ:MSVC10.0


OKは、それがMSVCのバグ(さらに別の1)だそうです。誰かが回答のバグについて詳しく説明できる場合(つまり、再現するケースを要約すると)、私は喜んでそれを受け入れるでしょう。

+4

これは(正しく)GCC 4.7ではコンパイルされません。さらに別のMSVC++標準外の奇妙さ。彼らはたぶん、明示的にコンストラクタをマークすることを忘れてしまったので、それを調べるために ''を調べることができます。 – syam

+0

@syam:GCCでコンパイルできないのはうれしいですが、実際には奇妙なのは、最初の例がMSCVでコンパイルされているのに対し、もう1つはコンパイルされていないということです。それは本当に奇妙なものです –

+0

@ArmenTsirunyan VS2012でコンパイルしません。エラーメッセージは、コンストラクタが「明示的」であることを示します – Praetorian

答えて

7

実際にはバグではありません。問題は、最初のコードがコンパイルされないうちに2番目のコードを許可するのが間違っている可能性があることです。

std::vector<std::vector<int>> graph(5, 5); 

それはコンパイラのためにそれほど明確ではない:

問題は、それはあなたが行うときに呼び出したいものをコンストラクタあなたに明白なようだしながら、ということです。

vector(size_type,const T& value = T()); 

template <typename InputIterator> 
vector(InputIterator first, InputIterator last); 

第が完全一致であることがされるように最初のものは、(符号なしである)size_type5の変換を必要とする。特に、潜在的に引数を受け入れることができる2つのコンストラクタのオーバーロードがありますコンパイラによってピックアップされたもの...

...どのようなC++ 03標準が効果的に義務付けることは2番目の引数は明示的であるということである

vector(static_cast<size_type>(first),static_cast<T>(last)) 

:それはへの呼び出しであるかのように推定されるタイプInputIteratorが不可欠な振る舞いである場合は、コンパイラは、という2番目のオーバーロードが必要です元のタイプintから宛先タイプstd::vector<int>に変換されます。変換が明示的であるため、エラーが発生します。

C++ 11標準では、SFINAEを使用してイテレータのコンストラクタを無効にし、引数が実際に入力イテレータでない場合、C++ 11コンパイラでコードを拒否するように変更していますいくつかはバグであると主張している)。

-4

std :: vector < int>はsize_typeとconst int &を受け入れるコンストラクタを持っています。これは、この場合呼び出されると予想されるコンストラクタです。ベクトルを初期化して5つの整数を持ち、それぞれ5の値を持ちます。

+3

私の質問ではっきりと読めるように、 * –

+0

@ArmenTsirunyanコンパイラのバグ。 – selalerer

+0

あなたの答えが理にかなっていない場合 –

1

これは実際には拡張であり、バグではありません。

呼び出されるコンストラクタは、2つのイテレータを使用するコンストラクタです(実際は、同じタイプの2つのパラメータに一致します)。 2つのイテレーターが実際にはintである場合の特殊化が呼び出されます。具体的には、endの値を使用してvalue_typeを構成し、そのベクトルにbeginのコピーを移入します。

+0

私は理解しているとは思わない... intはイテレータとして何を意味するのだろうか? –

+0

@ArmenTsirunyan: 'std :: vector'には、イテレータの開始と終了を行うコンストラクタがあります。これは 'template vector(_It first、_It last)'のように定義されています。これはあなたの呼び出しに一致します。次に、 '_It'が' int'である場合を処理する過負荷の1つである '_It'の型に基づいて、さまざまなオーバーロードを持つ関数を呼び出します。 –

+0

あなたの質問に答えるために、iteratorは__not__ですが、コードはintに渡す場合を処理します。 –

2

私にはこのコンストラクタを呼び出しているように見えます:

template <class InputIterator> 
vector (InputIterator first, InputIterator last, 
    const allocator_type& alloc = allocator_type()); 

私はコンストラクタが複数のパラメータを取りますのでexplicitが、それに入ってくる場所がわからないんだけど。 intからベクトルへの自動キャストではありません。

+0

標準では、2つのイテレータコンストラクタを使用することを明示的に禁止しています。 –

+0

私は理解しているとは思わない... intはどのように入力イテレータですか? –

+0

'InputIterator'はテンプレートパラメータに過ぎません。どのタイプでもかまいません。 –

関連する問題