SFINAE 在重载决议之外?

SFINAE outside of overload resolution?

在他的演讲现代模板元编程:纲要第 I 部分中,Walter Brown 以他的方式讨论 enable_if 与 SFINAE 的交互。

在大约 47:40 的谈话中,他被问到一个问题,我无法完全匹配他对所问问题的回答。然而,问题的症结似乎在于他是在说 SFINAE 独立于重载解析,恰好常用于函数的重载解析。

我理解他的回答的方式是他也在说SFINAE还有另一个用途。

除了重载解析之外,SFINAE 还能应用到哪些地方?在听到他对这个问题的回答之前,我的理解是它唯一的用途是重载解析。

编辑:谈话就在这里https://www.youtube.com/watch?v=Am2is2QCvxY

如果您认为合适,您可以根据参数禁用任何模板。

例如,可以想象一个矩阵 class 应该只用算术类型实例化。也就是说,我们希望允许实数和整数矩阵而不是字符串矩阵。你可以这样做:

#include <type_traits>

template<typename T,
         typename = typename std::enable_if<std::is_arithmetic<T>::value>::type>
class Matrix
{
  // ...
};

现在,如果用户 Matrix<double> m {} 它会顺利编译,但是 Matrix<std::string> 会给出一个简单的错误消息,指出没有定义这种类型。这可能会帮助用户提供超过页面的错误消息,即矩阵 class 的某些内部结构没有为 std::string 操作数生成有效代码。

另一个用例是在模板的部分特化中进行选择。这可能是一个愚蠢的例子,但它可能会给你一个想法。假设我们有一个带有两个类型参数的模板,并且想要专门处理它们都引用相同类型的情况。但是,如果类型小于 int,特化(出于某些不明确的原因)比主模板差,所以在这种情况下我们不需要它。

#include <iostream>
#include <type_traits>

template<typename T1, typename T2>
struct X
{
  void
  operator()()
  {
    std::cout << "I'm the primary template." << std::endl;
  }
};

template<typename T>
struct X<T, typename std::enable_if<(sizeof(T) >= sizeof(int)), T>::type>
{
  void
  operator()()
  {
    std::cout << "I'm the partial specialization." << std::endl;
  }
};

int
main()
{
  X<int, float> int_float {};  // primary template
  X<int, int> int_int {};      // partial specialization
  X<char, char> char_char {};  // primary template!
  int_float();
  int_int();
  char_char();
}

我系统上的输出:

I'm the primary template.
I'm the partial specialization.
I'm the primary template.