简单SFINAE示例过载函数不编译

时间:2018-04-07 01:33:32

标签: c++ c++11 templates template-meta-programming sfinae

我指的是这个例子SFINAE example

我试图运行该示例,

//enable_if
template<bool, typename T = void>
struct enable_if {};
template <typename T>
struct enable_if<true, T> {
    using type = T;
};

template <typename T>
void do_stuff(typename enable_if<std::is_integral<T>::value, T>::type &t) {
    std::cout<< "Integral selected "<<std::endl;
}

template <typename T>
void do_stuff(typename enable_if<std::is_class<T>::value, T>::type &t) {
    std::cout<<"Class selected " <<std::endl;
}

int main()
{
    int t =25;
    do_stuff(t);
    return 0;
}

但是这不会编译,我可以知道为什么吗?

3 个答案:

答案 0 :(得分:3)

除了其他解决方案之外,如果您不希望将enable_if作为返回值,则可以将其作为参数类型传递,然后将其作为函数签名的一部分:

#include <type_traits>
#include <iostream>

//enable_if
template<bool, typename T = void>
struct enable_if {};
template <typename T>
struct enable_if<true, T> {
    using type = int; // must be a non-type template parameter
};

template <typename T, typename enable_if<std::is_integral<T>::value, T>::type = 0>
void do_stuff(T &t) {
    std::cout<< "Integral selected "<<std::endl;
}

template <typename T, typename enable_if<std::is_class<T>::value, T>::type = 0>
void do_stuff(T &t) {
    std::cout<<"Class selected " <<std::endl;
}

class Foo
{
  public:
    Foo() = default;
};

int main()
{
    int t =25;
    Foo f;
    do_stuff(t);
    do_stuff(f);
    return 0;
}

答案 1 :(得分:1)

这对我有用:

template <typename T>
typename enable_if<std::is_integral<T>::value, void>::type
do_stuff(T& t) {
    std::cout<< "Integral selected "<<std::endl;
}

template <typename T>
typename enable_if<std::is_class<T>::value, void>::type
do_stuff(T& t) {
    std::cout<<"Class selected " <<std::endl;
}

问题是enable_if静态调用应用于函数参数而不是返回类型。

答案 2 :(得分:0)

  

但是这不会编译,我可以知道为什么吗?

因为,调用do_stuff()类型T无法通过enable_if推断出来。

但如果您致电do_stuff()来说明T

类型,则无效
int t =25;
do_stuff<int>(t); // compile

为了避免这个问题,我建议您使用Nicolas Tisserand(+1)提出的解决方案(不需要将void作为enable_if的第二个参数进行说明,因为它是默认值)

template <typename T>
typename enable_if<std::is_integral<T>::value>::type
do_stuff(T& t) {
    std::cout<< "Integral selected "<<std::endl;
}

template <typename T>
typename enable_if<std::is_class<T>::value>::type
do_stuff(T& t) {
    std::cout<<"Class selected " <<std::endl;
}

通过返回类型启用SFINAE。

这种类型T可以从参数中推断出来,所以你不需要解释它。