4

次のコードを検討してください。

#include<iostream>
#include<utility>


struct Base
{
    int baseint;
};

struct Der1 : Base
{
    int der1int;
    Der1() : der1int(1) {}
    explicit Der1(const Base& a) : Base(a), der1int(1)
    {
        std::cerr << "cc1" << std::endl;
    }
};

struct Der2 : Base
{
    int der2int;
    Der2() : der2int(2) {}
    explicit Der2(const Base& a) : Base(a), der2int(2)
    {
        std::cerr << "cc2" << std::endl;
    }
};


template <typename T, typename U>
struct MyPair
{
    T first;
    U second;
};

int main()
{
    Der1 d1;
    Der2 d2;

    std::pair<Der1, int> p1;
    std::pair<Der2, int> p2;

    p1 = p2; // This compiles successfully

    MyPair<Der1, int> mp1;
    MyPair<Der2, int> mp2;

    mp1 = mp2; // This will raise compiler error, as expected.
}

GCC4.5.2でテスト済み

理由はstd::pair情報源にあります:

  /** There is also a templated copy ctor for the @c pair class itself.  */
  template<class _U1, class _U2>
    pair(const pair<_U1, _U2>& __p)
    : first(__p.first),
      second(__p.second) { }

その動作はC++標準に準拠していますか?一見すると、一貫性がなく、直感に反しているように見えます。STLの他の実装も同じように機能しますか?

4

4 に答える 4

5

質問を理解できるかどうかはわかりませんが、基本的にstd::pair、インスタンス化タイプが暗黙的に変換可能でなくても、2つの無関係なものが暗黙的に変換可能である理由を尋ねています。つまり、インスタンス化タイプの暗黙的に変換可能なプロパティがペアに伝播しないのはなぜですか。

この標準では、テンプレートに明示的な代入演算子は提供されていませんstd::pair。つまり、暗黙的に生成された代入演算子が使用されます。変換可能なタイプのペアを割り当てることができるようにするために、それはからへの暗黙の変換を可能にするテンプレート化されたコンストラクターに依存します。その動作は§20.2.2[lib.pairs]/4で定義されています。std::pair<A,B>std::pair<C,D>

template<class U, class V> pair(const pair<U, V> &p);

効果:引数の対応するメンバーからメンバーを初期化し、必要に応じて暗黙的な変換を実行します。

標準は、暗黙の変換を使用するための実装のみを要求しているようであり、この特定の実装では、変換は実際には明示的であり、標準の表現と矛盾しているようです。

于 2011-07-20T11:11:54.713 に答える
2

クラスstd::pairの一部としてコンストラクター

template<class T1, T2>
class pair
{
public:

    template<class _U1, class _U2>
    pair(const pair<_U1, _U2>& __p)
         : first(__p.first),
           second(__p.second)
    { } 

};

はコピーコンストラクタではなく、anypair<_U1, _U2>から。への変換コンストラクタpair<T1, T2>です。firstこれは、とsecondメンバーが他のペアの対応するメンバーに変換可能な場合に機能します。

各メンバーを個別に変換することは、標準に従っています。

于 2011-07-20T11:08:37.947 に答える
1

これは本当にコメントであるはずですが、私はこれを入力するためのいくらかの余地を好みます。

したがって、2つのタイプがあるとしましょう。

typedef std::pair<A,B> pairAB;
typedef std::pair<S,T> pairST;

ここで、一方を他方に割り当てたいと思います。

pairAB x;
pairST w;

x = w; // how?

std::pair明示的な代入演算子がないため、デフォルトの代入のみを使用できますpairAB & operator=(const pairAB &)したがって、暗黙の変換コンストラクターを呼び出します。これは、次と同等です。

x = pairAB(w);  // this happens when we say "x = w;"

ただし、指摘されているように、この変換コンストラクターは明示的なメンバーコンストラクターを呼び出します。

pairAB(const pairST & other) : first(other.first), second(other.second) { }

したがって、メンバーごとに個別に明示的な変換を使用します。

于 2011-07-20T11:28:05.713 に答える
0

クイックアンサー:標準ではそうすべきだと言われているからです。

もちろん、あなたの次の質問は次のようになります:なぜ標準はそう言うのですか?

この行を想像してみてください。これは、機能するはずだとあなたが同意すると思います。

std::pair<long, long> x = std::make_pair(3, 5);

しかし、35はintであるため、をに割り当てようとしstd::pair<int, int>ていstd::pair<long, long>ます。テンプレート化されたコンストラクターとテンプレート化された代入演算子がないと、MyPair証明したように失敗します。

だからあなたの質問に答えるために:テンプレート化されたコンストラクターは便利です。誰もがintをlongに割り当てることができることを期待しています。したがって、たとえば、intのペアをlongのペアに割り当てることができるのは合理的です。

于 2011-07-20T11:06:38.303 に答える