如何借助 std::enable_if 定义模板函数

How to define a template function with the help of std::enable_if

我想做的是定义一个模板函数,它只能由 class 特化,它继承了一些 classes.

比如我已经有两个classBase1Base2。我正在尝试定义这样一个模板函数:

template<typename T>  // if (std::is_base_of<Base1, T>::value || std::is_base_of<Base2, T>::value)
std::ostream & operator<<(std::ostream &os, const T& t)
{
    // os << t.member1 << t.member2...;
    return os;
}

好像std::enable_if能帮上忙,但我不知道怎么帮。

C++11

template <typename T, typename = typename std::enable_if<
                          std::is_base_of<Base1, T>::value ||
                          std::is_base_of<Base2, T>::value>::type>
std::ostream &operator<<(std::ostream &os, const T &t) {
  // os << t.member1 << t.member2...;
  return os;
}

或:

template <typename T, typename std::enable_if<
                          std::is_base_of<Base1, T>::value ||
                          std::is_base_of<Base2, T>::value>::type * = nullptr>
std::ostream &operator<<(std::ostream &os, const T &t) {
  // os << t.member1 << t.member2...;
  return os;
}

当想要提供仅在 SFINAE 谓词上不同的互斥 SFINAE 约束重载时,后一种方法可能很有用。在这种情况下,前一种方法不可行,因为两个仅在默认模板参数方面不同的模板函数声明相同的函数模板,因为默认模板参数不是函数模板签名的一部分。

C++14(使用 std::enable_if_t 实用程序别名模板)

template <typename T,
          typename = std::enable_if_t<std::is_base_of<Base1, T>::value ||
                                      std::is_base_of<Base2, T>::value>>
std::ostream &operator<<(std::ostream &os, const T &t) {
  // os << t.member1 << t.member2...;
  return os;
}

C++17(使用_v实用变量模板)

template <typename T, typename = std::enable_if_t<std::is_base_of_v<Base1, T> ||
                                                  std::is_base_of_v<Base2, T>>>
std::ostream &operator<<(std::ostream &os, const T &t) {
  // os << t.member1 << t.member2...;
  return os;
}