C++ 11:const、揮発性、左辺値参照、および右辺値参照修飾メンバー関数ポインタを抽象化?



c++ 右辺値参照 (1)

あなたは単にあなたのテンプレートを特殊化することを考えましたか?

2つのバージョンを追加するだけです。

template <typename Object>
struct Bar<Object&> {
  typedef int (Object::*Sig)(int)&;
};

template <typename Object>
struct Bar<Object&&> {
  typedef int (Object::*Sig)(int)&&;
};

そして、コンパイラは適切な特殊化(または一般的な場合へのフォールバック)を適切に選択します。

これは、 const / volatileからあなたを救いますが、コードを3回書く必要があることを意味します。

C ++ 03では、関数パラメータをconstvolatile 、および/または左辺値参照( & )として修飾できます。

C ++ 11では、もう1つ、右辺値参照( && )が追加されています。

さらに、C ++では、パラメータの修飾子に基づいて関数をオーバーロードできるため、関数を呼び出すときに最も適切なオーバーロードが選択されます。

メンバー関数は、概念的には、その型がメンバーであるクラスのインスタンスへの参照である、追加のパラメーターを取る関数と考えることができます。 他のパラメータとほぼ同じ方法で、この「追加のパラメータ」の修飾子に基づいてメンバ関数をオーバーロードすることは可能です。 これは、関数シグネチャの末尾に修飾子を付けることによって表現されます。

struct Foo
{
    int& data();             // return a non-const reference if `this` is non-const
    const int& data() const; // return a const reference if `this` is const
};

C ++ 03では、 constおよびvolatile修飾子が使用可能であり、C ++ 11では&および&&も許可されています( &はC ++ 03では理論的には許可されていましたが、できませんでした)。

&&&が相互に排他的であることを除いて、修飾子の任意の組み合わせを使用できます。これは、C ++ 03では2 ^ 2 = 4、C ++ 11では2 ^ 4-4 = 12の可能性があります。

メンバ関数ポインタを扱う場合、これは非常に面倒です。これらは、これらの修飾子では少しも多相ではないためです。引数として渡されるメンバ関数ポインタの " this type"の修飾子は完全に一致する必要があります。渡されるパラメータの型に関するもの。 C ++では、修飾子を抽象化するための明示的な機能も提供されていません。 C ++ 03ではこれは大体OKでした、なぜならあなたはconst版と非const版を書く必要があり、 volatile気にする人は誰もいないでしょうが、C ++ 11の病理学的な場合(それほど珍しくありません)あなたは手動で最大12の過負荷を書く必要があるかもしれません。 機能ごと

囲んでいるクラスの型をテンプレートパラメータとして渡して、そこからメンバ関数ポインタの型を派生させる場合、 constおよびvolatile修飾子は期待どおりに許可および伝播されることを発見できてとてもうれしいです。

template<typename Object>
struct Bar
{
    typedef int (Object::*Sig)(int);
};

Bar<Baz>;                // Sig will be `int (Baz::*)(int)`
Bar<const Baz>;          // Sig will be `int (Baz::*)(int) const`
Bar<volatile Baz>;       // Sig will be `int (Baz::*)(int) volatile`
Bar<const volatile Baz>; // Sig will be `int (Baz::*)(int) const volatile`

これは、すべてのケースを手動で書き出す必要があるよりもはるかに優れています。

残念ながら、 &&&にはうまくいかないようです。

GCC 4.7によると、

エラー:参照型 'Baz &&'へのポインタの形成

しかし、4.7の時点でGCCがまだthisに関する参照修飾子をサポートしていないことを考えると、それはそれほど驚くべきことではありません。

私はClang 3.0でも試してみました。Clang3.0にはそのようなサポートがあります。

エラー:メンバポインタは非クラス型 'Baz &&'を参照しています

しかたがない。

これは不可能であり、 " this type "のメンバー関数ポインタについて参照修飾子を抽象化する方法はないと私は結論づけることができますか。 テンプレートパラメータとして " this type"を渡す場合の特定の場合を除いて、(特にthis )修飾子を抽象化するためのその他のテクニックも評価されるでしょう。

(C ++がメンバ関数と通常の関数を区別しなければ、これはすべて簡単なことです。関数(ポインタ)のパラメータの型としてテンプレートパラメータを使用し、テンプレート引数はそのままの状態で渡され、修飾子はそのまま使用されます。追加の考慮は必要ありません。)





qualifiers