#include <iostream>
#include <type_traits>
struct Y {
void f(int i) {}
};
template<bool B,typename T=void>
using Enable_if = typename std::enable_if<B, T>::type;
struct substitution_failure {};
template<typename T>
struct substitution_succeeded : std::true_type
{};
template<>
struct substitution_succeeded<substitution_failure>:std::false_type
{};
template<typename T>
struct get_f_result {
private:
template<typename X>
static auto check(X const& x)->decltype(f(x));
static substitution_failure check(...);
public:
using type = decltype(check(std::declval<T>()));
};
template<typename T>
struct has_f:substitution_succeeded<typename get_f_result<T>::type>
{};
template<typename T>
constexpr bool Has_f() {
return has_f<T>::value;
}
template<typename T>
class X {
public:
template<typename U=T>
Enable_if<Has_f<U>()> use_f(const U& t) {
f(t);
}
};
int main()
{
std::cout << Has_f<Y>();
}
我知道这个问题在SO上可能是重复的,一式三份或n重复的,但是我没有找到令人信服的答案,因此我将重新发布该问题。为什么上面的代码说明Y
具有没有 f
函数。我使用Visual Studio 2017和GCC 7.3.0进行了尝试。我还在SO中找到了更简单的代码,可以正常工作。但是我不明白为什么这段代码不起作用。起作用的代码如下:
#include <iostream>
#include <type_traits>
using namespace std;
struct Hello
{
int helloworld() { return 0; }
};
struct Generic {};
// SFINAE test
template <typename T>
class has_helloworld
{
typedef char one;
typedef long two;
template <typename C> static one test(decltype(&C::helloworld));
template <typename C> static two test(...);
public:
enum { value = sizeof(test<T>(0)) == sizeof(char) };
};
int main() {
std::cout << has_helloworld<Hello>::value << std::endl;
std::cout << has_helloworld<Generic>::value << std::endl;
std::getchar();
return 0;
}
答案 0 :(得分:1)
Stroustrup的代码检查是否有使用该类型的单个参数的自由函数。相反,您的Y
类具有成员函数。
也就是说,他的代码采用类型T
,并检查调用f(instance of T)
的格式是否正确。您可以在use_f
中看到此内容。您的代码需要调用(instance of T).f(instance of int)
。
定义Y
类以完成检查causes an output of 1:
struct Y {};
void f(Y);
或者,change the check与您的班级一起工作,也要注意更改const
,因为您的成员函数是非常量的:
template<typename T>
struct get_f_result {
private:
template<typename X>
static auto check(X& x)->decltype(x.f(0));
static substitution_failure check(...);
public:
using type = decltype(check(std::declval<T&>()));
};