テンプレート パラメーターがメソッド (またはその親クラスの 1 つ) を実装していることをテンプレート内でアサートする簡単な方法が必要です。私は概念チェックライブラリを読みましたが、このような単純なチェックを行う簡単な例を見つけるのは難しいです.
私は他の投稿(この投稿やこの投稿など)をフォローしようとしましたが、これを変更して、多くのメソッドタイプ(私の例ではFoo(メソッド名)とhas_foo(チェッカー名))で汎用的にできるようにしました。マクロ引数としてラップされるため、任意のメソッドに使用できます)
私が今持っているコードはこれです:
template <typename TypeToBeChecked, typename Sign>
class has_foo {
static_assert( false , "inside root declaration of " "has_foo" );
public:
static const bool result = false;
};
template <typename TypeToBeChecked , typename R>
class has_foo < TypeToBeChecked , R(void) >
{
static_assert( false , "inside specialization of " "has_foo" " for R(void)" );
class yes { char m;};
class no { yes m[2];};
struct BaseMixin { R Foo(){} };
struct Base : public TypeToBeChecked, public BaseMixin {};
template <typename T, T t> class Helper{};
template <typename U> static no deduce(U*, Helper<R (BaseMixin::*)(), &U::Foo>* = 0);
static yes deduce(...);
public:
static const bool result = sizeof(yes) == sizeof(deduce((Base*)(0)));
};
template <typename TypeToBeChecked , typename R , typename ARG1>
class has_foo< TypeToBeChecked , R(ARG1) >
{
static_assert( false , "inside specialization of " "has_foo" " for R(ARG1)" );
class yes { char m;};
class no { yes m[2];};
struct BaseMixin { R Foo(ARG1){} };
struct Base : public TypeToBeChecked, public BaseMixin {};
template <typename T, T t> class Helper{};
template <typename U>
static no deduce(U*, Helper<R (BaseMixin::*)(ARG1), &U::Foo>* = 0);
static yes deduce(...);
public:
static const bool result = sizeof(yes) == sizeof(deduce((Base*)(0)));
};
template <typename TypeToBeChecked , typename R , typename ARG1 , typename ARG2>
class has_foo< TypeToBeChecked , R(ARG1, ARG2) >
{
static_assert( false , "inside specialization of " "has_foo" " for R(ARG1 , ARG2)" );
class yes { char m;};
class no { yes m[2];};
struct BaseMixin { R Foo(ARG1,ARG2){} };
struct Base : public TypeToBeChecked, public BaseMixin {};
template <typename T, T t>
class Helper{};
template <typename U>
static no deduce(U*, Helper<R (BaseMixin::*)(ARG1,ARG2), &U::Foo>* = 0);
static yes deduce(...);
public:
static const bool result = sizeof(yes) == sizeof(deduce((Base*)(0)));
};
template< typename Type >
struct Connector
{
static_assert( has_foo< Type , int(int, double) >::result , "Type has no Foo method" );
void Operate() {
Type t;
t.Foo(3);
}
};
struct Bla1 { int Foo(double f) { return (int)f; } };
struct Bla2 { int Foo(int g, double h) { return g+(int)h;} };
int main()
{
//Connector< Bla1 > a;
Connector< Bla2 > b;
};
このサンプル コードをコンパイルすると (g++ 4.4.3 ubuntu で -std=c++0x オプションを指定すると、static_assert が認識されます)、次のようになります。
$ g++ test.cpp -std=c++0x -o test
test.cpp:72: error: static assertion failed: "inside root declaration of has_foo"
test.cpp:79: error: static assertion failed: "inside specialization of has_foo for R(void)"
test.cpp:93: error: static assertion failed: "inside specialization of has_foo for R(ARG1)"
test.cpp:108: error: static assertion failed: "inside specialization of has_foo for R(ARG1 , ARG2)"
そこで待ってください (Connector< Bla1 > a がコメントされていることに注意してください) 私の最初の質問は次のとおりです。
1) アサーションが評価されている場合、含まれているテンプレートがインスタンス化されていると仮定するのは正しいですか?
編集: GMan による回答: static_assert は、テンプレートがインスタンス化されたときではなく、解析中に評価されます。false を sizeof(TypeToBeChecked)==0 に置き換えると、コンパイル時にバインドされます
2) コネクタ テンプレート クラス内の静的アサートが int(int, double) シグネチャを使用して has_foo をインスタンス化しているため、単一パラメーターおよびパラメーターなしの特殊化をインスタンス化するべきではないと仮定するのは正しいですか? 私の仮定の何が問題なのですか?
編集:この仮定は正しいですが、1)の答えに従って修正したので、インスタンス化プロセスは期待どおりに動作しています
3) Connector< Bla1 > 行のコメントを外すと、失敗すると予想されます (Bla1 には 1 つのパラメーター署名を持つ Foo しかないためです。ただし、そうではありません。何が問題なのか、特に最初の考慮事項を考慮してリンクされた投稿