有没有办法否定一个对象是否存在函数?
Is there a way to get the negation of if a function exists for an object?
判断一个函数是否存在函数,可以使用如下:
template <typename...Ts>
using void_t = void;
void fn(int);
struct X {};
template <typename T, typename = void_t<decltype(fn(std::declval<T>()))>>
void fn2(T) { }
void test() {
fn2(int(1)); // works
//fn2(X()); // doesn't work
}
现在,有没有办法检测类型 T
是否存在 fn(T)
?
示例:
void test2() {
//fn2(int(1)); // doesn't work
fn2(X()); // works
}
这样做的原因是为了定义一个排除操作,这样我就可以为两者定义fn2()
以避免歧义错误。
您需要 fn2
的另一个重载,否则 SFINAE 将无法执行任何有用的操作。
void fn2(...) { } // called if the overload below is SFINAEd away
template <typename T, typename = void_t<decltype(fn(std::declval<T>()))>>
void fn2(T) { }
想法是 SFINAE 可以从重载集 中删除 个候选人。如果 fn2
是唯一的候选者,那么您将遇到硬错误。
通常的做法是创建类型特征,正如@chris 所说:
template <typename T, typename = void>
struct fn_callable_with : std::false_type {};
template <typename T>
struct fn_callable_with<T, void_t<decltype(fn(std::declval<T>()))>> : std::true_type {};
// For bonus C++14 points:
// template <typename T>
// /*C++17: inline*/ constexpr bool fn_callable_with_v = fn_callable_with<T>::value;
template <typename T, typename = typename std::enable_if<!fn_callable_with<T>::value>::type>
// C++14: template <typename T, typename = std::enable_if_t<!fn_callable_with_v<T>>>
void fn2(T) { }
判断一个函数是否存在函数,可以使用如下:
template <typename...Ts>
using void_t = void;
void fn(int);
struct X {};
template <typename T, typename = void_t<decltype(fn(std::declval<T>()))>>
void fn2(T) { }
void test() {
fn2(int(1)); // works
//fn2(X()); // doesn't work
}
现在,有没有办法检测类型 T
是否存在 fn(T)
?
示例:
void test2() {
//fn2(int(1)); // doesn't work
fn2(X()); // works
}
这样做的原因是为了定义一个排除操作,这样我就可以为两者定义fn2()
以避免歧义错误。
您需要 fn2
的另一个重载,否则 SFINAE 将无法执行任何有用的操作。
void fn2(...) { } // called if the overload below is SFINAEd away
template <typename T, typename = void_t<decltype(fn(std::declval<T>()))>>
void fn2(T) { }
想法是 SFINAE 可以从重载集 中删除 个候选人。如果 fn2
是唯一的候选者,那么您将遇到硬错误。
通常的做法是创建类型特征,正如@chris 所说:
template <typename T, typename = void>
struct fn_callable_with : std::false_type {};
template <typename T>
struct fn_callable_with<T, void_t<decltype(fn(std::declval<T>()))>> : std::true_type {};
// For bonus C++14 points:
// template <typename T>
// /*C++17: inline*/ constexpr bool fn_callable_with_v = fn_callable_with<T>::value;
template <typename T, typename = typename std::enable_if<!fn_callable_with<T>::value>::type>
// C++14: template <typename T, typename = std::enable_if_t<!fn_callable_with_v<T>>>
void fn2(T) { }