Reputation: 61
In my TClass<T>::foo()
function, I'd like to invoke a T
instance if and only if T
is a function type.
#include <iostream>
#include <functional>
template<class T>
struct TClass
{
TClass(T value) : value(value) {}
T value;
void foo()
{
// if(value is std::function)
// call function;
}
};
int main()
{
TClass<int> t1{0};
t1.foo();
TClass<std::function<void()>> t2{[](){ std::cout << "Hello, World!\n"; }};
t2.foo();
}
How can I do that?
Upvotes: 6
Views: 194
Reputation: 2053
Why not partial specialization ?
Consider:
#include <iostream>
#include <functional>
template<class T>
struct TClass {
TClass(T value) : value(value) {}
T value;
void foo() {
std::cout << "T - other" << std::endl;
}
};
template<class T>
struct TClass<std::function<T>> {
TClass(std::function<T> value) : value(value) {}
std::function<T> value;
void foo() {
std::cout << "std::function" << std::endl;
}
};
Upvotes: 2
Reputation: 37696
In C++17 you can do:
void foo() {
if constexpr (std::is_invocable_v<T>) {
value();
}
}
If you only wants to allow std::function
, you'll need your own trait, e.g.:
template <class T>
struct is_stdfunction: std::false_type {};
template <class T>
struct is_stdfunction<std::function<T>: std::true_type {};
template <class T>
constexpr bool is_stdfunction_v = is_stdfunction<T>::value;
// Then in foo():
void foo() {
if constexpr (is_stdfunction_v<std::decay_t<T>>) {
value();
}
}
Upvotes: 4
Reputation: 304122
In C++11, the easiest way to do this is to re-deduce the value through a helper function:
template <typename U>
auto foo_helper(U const& f, int) -> decltype(f()) {
return f();
}
template <typename U>
void foo_helper(U const&, long) {}
void foo() {
foo_helper(value, 0);
}
The conversion from 0
to int
is better than its conversion to long
, so if the first overload is viable - it will be preferred. If the first overload isn't viable, then we call the second one.
If you really care only about std::function
, then we can just have simpler overloads:
void foo_helper(std::function<void()> const& f) {
f();
}
template <typename T>
void foo_helper(T const&) { }
void foo() {
foo_helper(value);
}
Upvotes: 7