在我的TClass<T>::foo()
函数中,当且仅当T
是函数类型时,我才想调用T
实例。
#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();
}
我该怎么做?
答案 0 :(得分:7)
在C ++ 11中,最简单的方法是通过辅助函数重新推导出值:
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);
}
从0
到int
的转换优于转换为long
,因此如果第一次重载是可行的 - 那么它将是首选。如果第一次过载不可行,那么我们称之为第二次过载。
如果您真的只关心 关于std::function
,那么我们可以有更简单的重载:
void foo_helper(std::function<void()> const& f) {
f();
}
template <typename T>
void foo_helper(T const&) { }
void foo() {
foo_helper(value);
}
答案 1 :(得分:4)
在C ++ 17中,你可以这样做:
void foo() {
if constexpr (std::is_invocable_v<T>) {
value();
}
}
如果您只想允许std::function
,那么您需要自己的特质,例如:
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();
}
}
答案 2 :(得分:2)
考虑:
#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;
}
};