問題は暗黙の変換です。int
からで
はありませんstd::vector<int>
; そこに含まれるコンストラクターが宣言されているexplicit
ため、これは機能しません。したがって、暗黙の変換には使用できません。暗黙の変換はfromstd::pair<int, int>
から
std::pair<int, std::vector<int> >
。です。これは、テンプレートから派生したコンストラクターを使用しますtemplate <typename U1, typename U2> std::pair(
std::pair<U1, U2> const& )
。これは暗黙的ではありません。そして、このコンストラクターの定義は次のとおりです。
template <typename T1, typename T2>
template <typename U1, typename U2>
std::pair<T1, T2>::std::pair( std::pair<U1, U2> const& other )
: first( other.first )
, second( other.second )
{
}
(これは、標準で指定されている方法とは異なります。ただし、C ++ 03の仕様では、他の多くのことは許可されていません。C++ 11では、可能な場合に移動して構築できるように、余分な荷物がたくさんありますが、私は最終的な効果は同じだと思います。)
このコンストラクターでは、暗黙的な変換ではなく、コンストラクターの明示的な呼び出しがあることに注意してください。したがって、の暗黙的な変換がpair
機能するには、2つのタイプが明示的に変換可能であるだけで十分です。
個人的には、これが本来の意図ではなかったと思います。実際、言語に追加される前に周囲の言語のほとんどstd::pair
が凍結explicit
されていたのではないかと思うので、問題はありませんでした。その後、誰もこの問題を再検討することを考えませんでした。また、C ++ 11では、再検討すると下位互換性が失われます。したがって、予期しない変換が発生します。
転送によって明示的な変換が暗黙的になるのは、これだけではないことに注意してください。検討:
std::vector<std::vector<int> > v2D( 5, 10 );
明らかに、で10
はありませんstd::vector<int>
(これは、2番目の引数がどうあるべきかです)。しかし...C++ 03では、これはコンストラクターテンプレートと一致します。
template<typename ForwardIterator, typename ForwardIterator>
std::vector( ForwardIterator begin, ForwardIterator end );
そして、標準にはこれのためのいくつかの特別な言語があります:
—コンストラクター
template <class InputIterator>
X(InputIterator f, InputIterator l, const Allocator& a = Allocator())
次と同じ効果があります:
X(static_cast<typename X::size_type>(f),
static_cast<typename X::value_type>(l), a)
InputIteratorが整数型の場合。
そして、暗黙の変換は明示的になりました。
(この特別な言語がないと、
std::vector<int> v(10, 42);
コンパイルに失敗します:上記のテンプレートコンストラクターのインスタンス化は完全一致であり、。よりも優れていstd::vector<int>( size_t, int
)
ます。委員会は、上記の最初の整数の明示的なキャストを要求することsize_t
は、おそらくあまりにも多くのユーザーに質問していると感じました。)
C ++ 11は、ここでの表現を大幅に変更しました。
std::vector<int, std::vector<int>> v2D( 10, 42 );
もはや合法ではありません。
少なくとも私が見ることができるような変更は、のコンストラクターには適用されませんでしたstd::pair
。