次のコードを抜粋しましたが、コンパイルされません。
#include <iostream>
struct A {
void foo() {}
};
struct B : public A {
using A::foo;
};
template<typename U, U> struct helper{};
int main() {
helper<void (A::*)(), &A::foo> compiles;
helper<void (B::*)(), &B::foo> does_not_compile;
return 0;
}
&B::foo
に解決されるためコンパイルされないため&A::foo
、提案された型と一致しませんvoid (B::*)()
。これは、非常に特定のインターフェイス (特定の引数の型と出力の型を強制しています) をチェックするために使用している SFINAE テンプレートの一部であるため、チェックを読みやすく保ちながら、継承とは無関係に機能するようにしたいと考えています。
私が試したことは次のとおりです。
引数の 2 番目の部分のキャスト:
helper<void (B::*)(), (void (B::*)())&B::foo> does_not_compile;
残念ながら、2 番目の部分が定数式として認識されず、失敗するため、これは役に立ちません。
それを確認するために、参照を変数に割り当ててみました。
constexpr void (B::* p)() = &B::foo; helper<void (B::* const)(), p> half_compiles;
このコードは clang 3.4 で受け入れられますが、g++ 4.8.1 では拒否され、誰が正しいのかわかりません。
何か案は?
編集:多くのコメントが問題のより具体的なバージョンを求めているため、ここに書きます:
私が探しているのは、クラスが特定のインターフェースを尊重していることを明示的に確認する方法です。このチェックは、テンプレート化された関数の入力引数を検証するために使用され、それらの関数が必要とするコントラクトを尊重し、クラスと関数に互換性がない場合にコンパイルが事前に停止するようにします (つまり、型特性の種類のチェック)。
したがって、要求する各メンバー関数の戻り値の型、引数の型と数、constness などを確認できる必要があります。最初の質問は、一致を検証するために使用しているより大きなテンプレートのチェック部分でした。