Reputation: 4522
I have following code:
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;
};
In other words, I want to know whether type has operator (). I thought that I can use SFINAE way to do this. However compiler tells:
'function_traits' : class template has already defined.
What's wrong with such code?
P.S.: here is simple usage:
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;
EDIT: I am using c++ 11 standard
Upvotes: 3
Views: 3469
Reputation: 18081
Maybe using the void_t
is much more simple:
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{};
It could be even simpler if your compiler provided concepts:
template<T>
concept bool CallableWithoutArgs= requires(T&& a){
(T&&)(a)();
};
Upvotes: 3
Reputation: 6425
Encouraged by a positive feedback, I will post a brief answer here.
The problem is that you cannot define a class twice, but you did this two times :-
template <typename T>
struct function_traits { .... some code ..... }
C++ doesn't allow that.
To check whether a function is exist, there is already a question about it, you can modify it to support the operator()
.
Here is a demo, very-slightly modified from Nicola Bonelli's answer there.
#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;
}
I just knew a few minutes ago that it also works for operator()
.
Edit: I changed typeof
to decltype
as StoryTeller and LmTinyToon recommended. Thank.
Upvotes: 6