1

コード

#include <iostream>

using namespace std;

#define PF         cout << __PRETTY_FUNCTION__ << endl;

class berlp {
public:
    berlp() { }
    void p() { }
};

template <typename T>
class derp {
public:
    derp() = default;

    derp(const T & a) : mem(a) {
        a.p();
        mem.p();

        PF
    }

    template <typename U>
    derp(U && a) : mem(std::forward<U>(a)) {
        PF
    }

    T       mem;
};

int main(int argc, const char * argv[])
{
    berlp                   one;
    derp<berlp &>           f(one);     // problems with this list below
    derp<const berlp &>     h(one);     // problem with this follows

    return 0;
}

XCode と CLang を使用した出力 これはすべて正常にコンパイルされ、出力は次のとおりです...

derp<berlp &>::derp(const T &) [T = berlp &]
derp<const berlp &>::derp(U &&) [T = const berlp &, U = berlp &]

問題

derp<berlp &> f(one);: derp コンストラクターの ap() は失敗するはずです。これは、"a" が参照の崩壊後の "const berlp &" であり、p() が const でないためです。次に、"a" (const berlp &) を使用した "mem" (berlp &) の初期化は機能しません。「derp(const T & a)」の「const」は何もしていないようです。最後に、const を壊さずにこのすべてを行うように見えるテンプレート化されたコンストラクターではなく、最初のコンストラクターを使用するのはなぜですか?

derp<const berlp &> h(one);: なぜこの呼び出しはテンプレート化されたコンストラクターを使用するのですか? 何も壊れないように見えるので、これはそれほど深刻な問題ではありませんが、コンストラクターで渡された berlp を変更できますが、他のコンストラクターは (おそらく) すべきではありません。

だから、私はひどく混乱しているか、何かが起きています! 助けてください!

4

1 に答える 1

1

ここには本当に複数の質問があります:

  1. なぜderp<berlp&>(one)最初のコンストラクターを使用するのですか?

    コンストラクターの宣言は、参照や参照参照などがないため、derp(T const&)に変わりderp(berlp& const&)、折りたたまれます。これは、8.3.2 [dcl.ref] パラグラフ 6 で述べられています。derp(berlp&)const

    typedef (7.1.3)、型テンプレート パラメータ (14.3.1)、または decltype-specifier (7.1.6.2) が型 T への参照である型 TR を示す場合、型 " 「cv TR への左辺値参照」は「T への左辺値参照」型を作成しますが、「cv TR への右辺値参照」型を作成しようとすると、TR 型が作成されます。

    berlp&明らかに、a を受け取るコンストラクターに a を渡すことberlp&は完全に一致し、テンプレート コンストラクターはそれ以上のことはできません。したがって、非テンプレート コンストラクターが選択されます。

  2. なぜ呼び出しderp<berlp&>(one)berlp動作するのですか?

    驚くべきことではありません: memis 型berlp&であり、 a で初期化されているberlp&ため、非constメンバーはすべて期待どおりに動作します。

  3. テンプレートコンストラクターを使用derp<berlp const&>して渡す場合berlp&、完全に一致し、明らかに選択されます。type のメンバー変数は、暗黙的に に変換される a でberlp const&初期化されるだけです。ここでも驚くことではありません。berlp&berlp const&

参照の折りたたみルールについて少し混乱していると思います。を間違った場所に配置することconstも役に立ちません。右に配置すると、実際にはほとんどの混乱が明確になるはずであり、右に配置することを好みconstます。

于 2013-10-01T05:14:42.153 に答える