【问题标题】:simple SFINAE example to overload function not compiling重载函数未编译的简单 SFINAE 示例
【发布时间】:2018-04-07 01:33:32
【问题描述】:

我指的是这个例子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;
}

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

【问题讨论】:

  • 我相信它们是相关但不同的问题。
  • @NicolasTisserand 不同的问题如何?它们是相同的问题。
  • OP 询问了他自己的自定义 enable_if 实现。其他问题与来自&lt;type_traits&gt; 的标准enable_if_t 相关。但最终的答案确实是相似的。
  • @NicolasTisserand 这正是实现enable_if 的方式——OP 没有使用std 版本的事实与问题无关。

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


【解决方案1】:

除了其他解决方案之外,如果您不想将 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;
}

【讨论】:

    【解决方案2】:

    这对我有用:

    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 静态调用被应用于函数参数而不是返回类型。

    【讨论】:

      【解决方案3】:

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

      因为,调用do_stuff()不能通过enable_if推导出类型T

      但是如果你调用 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 类型就可以从参数中推导出来,所以你不需要解释它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-26
        • 2017-08-16
        • 2012-09-10
        • 2017-03-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多