问题描述
我想检查是否存在签名适合参数包的成员函数。我从已知的 SFINAE 概念开始,同时尝试扩展它以考虑参数包。但此时我发现我不知道该怎么做。
我尝试做这样的事情:
// Note: T object may have several functions with the name foo,but with different signatures.
// a function foo also can be a template one with variadic parameters pack.
template<typename T,typename...Args>
class HAS_FUNCTION_FOO
{
template<typename U>
static bool test(decltype(&U::foo));
template<typename U>
static float test(...);
public:
static constexpr bool value = std::is_integral<decltype(test<T>(Args...))>::value;
//-------------------------------------------------------------^^^^^^^^^
// how to do it?
};
我想在编译时用它来声明特定的对象 - 像这样:
class Bar
{
public:
template<typename T,typename...Args>
void doSomthing(T* p,Args&&...parameters)
{
// get correct object type:
// if T has a function called foo with parameters fits for pack,then declare A,o.w declare B.
using ObjType = typename std::conditional<HAS_FUNCTION_FOO<T,Args>::value,A,B>::type;
// compute
ObjType::doSomthing(p,std::forward<Args>(parameters)...);
}
private:
struct A
{
template<typename T,typename...Args>
static void doSomthing(T* p,Args&&...parameters)
{
p->foo(std::forward<Args>(parameters)...);
}
};
struct B
{
template<typename T,Args&&...parameters)
{
// do something else
}
};
};
解决方法
可能是这样的:
template<typename T,typename...Args>
class HAS_FUNCTION_FOO
{
template <typename U>
static std::true_type test(
typename std::enable_if<sizeof(
decltype(std::declval<U>().foo(std::declval<Args>()...))*) != 0>::type*
);
template <typename U>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<T>(nullptr))::value;
};