如何用sfinae检查,type是否有operator()?
How to use sfinae to check, whether type has operator ()?
我有以下代码:
template <typename T>
struct function_traits
{
typedef decltype(&T::operator()) test_type;
typedef std::true_type res_type;
};
template <typename T>
struct function_traits
{
typedef std::false_type res_type;
};
也就是说,我想知道type有没有operator()。我以为我可以使用 SFINAE 的方式来做到这一点。然而编译器告诉:
'function_traits' : class template has already defined.
这样的代码有什么问题?
P.S.: 这里是简单的用法:
auto f1 = [](const int a){ std::cout << a << std::endl; };
function_traits<decltype(f1)>::res_type;
auto f2 = false;
function_traits<decltype(f2)>::res_type;
编辑:我使用的是 C++ 11 标准
受到积极反馈的鼓舞,我将post在这里做一个简短的回答。
问题是你不能定义一个 class 两次,但是你定义了两次 :-
template <typename T>
struct function_traits { .... some code ..... }
C++ 不允许这样做。
检查一个函数是否存在,已经有a question了,你可以修改它支持operator()
。
这是一个演示,从 Nicola Bonelli's answer 那里稍作修改。
#include <iostream>
struct Hello
{
void operator()() { }
};
struct Generic {};
// SFINAE test
template <typename T>
class has_parenthesis
{
typedef char one;
typedef long two;
template <typename C> static one test( decltype(&C::operator()) ) ;
template <typename C> static two test(...);
public:
enum { value = sizeof(test<T>(0)) == sizeof(char) };
};
int main(int argc, char *argv[])
{
std::cout << has_parenthesis<Hello>::value << std::endl; //print 1
std::cout << has_parenthesis<Generic>::value << std::endl; //print 0
return 0;
}
我几分钟前才知道它也适用于 operator()
。
编辑: 我将 typeof
更改为 decltype
作为 StoryTeller 和 LmTinyToon推荐。谢谢
也许使用 void_t
更简单:
template <typename T,class=void>
struct callable_without_args: std::false_type{};
template <typename T>
struct callable_without_args<T
,std::void_t<decltype(std::declval<T>()())>>
:std::true_type{};
如果您的编译器提供概念:
,它可能会更简单
template<T>
concept bool CallableWithoutArgs= requires(T&& a){
(T&&)(a)();
};
我有以下代码:
template <typename T>
struct function_traits
{
typedef decltype(&T::operator()) test_type;
typedef std::true_type res_type;
};
template <typename T>
struct function_traits
{
typedef std::false_type res_type;
};
也就是说,我想知道type有没有operator()。我以为我可以使用 SFINAE 的方式来做到这一点。然而编译器告诉:
'function_traits' : class template has already defined.
这样的代码有什么问题?
P.S.: 这里是简单的用法:
auto f1 = [](const int a){ std::cout << a << std::endl; };
function_traits<decltype(f1)>::res_type;
auto f2 = false;
function_traits<decltype(f2)>::res_type;
编辑:我使用的是 C++ 11 标准
受到积极反馈的鼓舞,我将post在这里做一个简短的回答。
问题是你不能定义一个 class 两次,但是你定义了两次 :-
template <typename T>
struct function_traits { .... some code ..... }
C++ 不允许这样做。
检查一个函数是否存在,已经有a question了,你可以修改它支持operator()
。
这是一个演示,从 Nicola Bonelli's answer 那里稍作修改。
#include <iostream>
struct Hello
{
void operator()() { }
};
struct Generic {};
// SFINAE test
template <typename T>
class has_parenthesis
{
typedef char one;
typedef long two;
template <typename C> static one test( decltype(&C::operator()) ) ;
template <typename C> static two test(...);
public:
enum { value = sizeof(test<T>(0)) == sizeof(char) };
};
int main(int argc, char *argv[])
{
std::cout << has_parenthesis<Hello>::value << std::endl; //print 1
std::cout << has_parenthesis<Generic>::value << std::endl; //print 0
return 0;
}
我几分钟前才知道它也适用于 operator()
。
编辑: 我将 typeof
更改为 decltype
作为 StoryTeller 和 LmTinyToon推荐。谢谢
也许使用 void_t
更简单:
template <typename T,class=void>
struct callable_without_args: std::false_type{};
template <typename T>
struct callable_without_args<T
,std::void_t<decltype(std::declval<T>()())>>
:std::true_type{};
如果您的编译器提供概念:
,它可能会更简单template<T>
concept bool CallableWithoutArgs= requires(T&& a){
(T&&)(a)();
};