編集済み:実際の解決策を提供しなかった元の回答とは完全に異なります。
このコードは、gcc 4.5.1 を使用する ideone でコンパイルされました。それは私ができる最善のことです。
#include <array>
#include <iostream>
using namespace std;
template<typename T>
struct has_property
{
struct UnmentionableType { UnmentionableType() {} };
//test if type has operator() (...)
template<typename U, typename A1, typename A2, typename A3, typename A4, typename A5>
static auto ftest(U* t, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) -> decltype((*t)(a1, a2, a3, a4, a5), char(0));
static std::array<char, 2> ftest(...);
public:
static const bool value = sizeof(ftest((T*)0, UnmentionableType(), UnmentionableType(), UnmentionableType(), UnmentionableType(), UnmentionableType())) == 1;
};
class c1
{
public:
int operator() () { return 0; }
};
class c2
{
public:
void operator() (int) { }
};
class c3
{
public:
template<typename... Args>
void operator() (Args... a) { }
};
class c4
{
public:
template<typename T>
void operator() (T t) { }
};
int main()
{
cout<<boolalpha<<has_property<c1>::value<<endl;
cout<<boolalpha<<has_property<c2>::value<<endl;
cout<<boolalpha<<has_property<c3>::value<<endl;
cout<<boolalpha<<has_property<c4>::value<<endl;
}
出力:
false
false
true
false
ノート:
1) 要求に応じて、可変個引数のテンプレート化された operator() でのみトリガーされます (ほぼ)
2)「完璧な」解決策ではありませんが、実用には十分なはずです。
残念ながら、gcc 4.5.1 はパラメーター パックを展開できません。私はこれがあなたのために働くかもしれないと思う:
template<typename U, typename... A>
static auto ftest(U* t, A... a) -> decltype((*t)(a...), char(0));
5 つ (またはそれ以上) のランダム型パラメーターを渡すのではなく、関数の真の可変性を実際にテストする方法はまだわかりません。
with_enable if の使用法 - 部分的なクラスの特殊化以外の解決策はありません。
//non-specialized
template<typename T, typename E=void>
class container
{
T* ptr;
public:
T* get() { return ptr; }
};
//specialization for class with appropriate operator()
template<typename T>
class container<T, typename std::enable_if<has_property<T>::value, void>::type>
{
T* ptr;
public:
T* get() { return ptr; }
template <typename... Args>
decltype(T::template operator ()(Args()...)) operator ()(Args... args) const
{
return (*get()).operator ()(args...);
}
};