Enable_if 的用法

函数返回值

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <type_traits>

template <typename T>
typename std::enable_if<std::is_integral<T>::value, T>::type
foo(T t) {
    std::cout << "Integer: " << t << std::endl;
    return t;
}

template <typename T>
typename std::enable_if<std::is_floating_point<T>::value, T>::type
foo(T t) {
    std::cout << "Floating point: " << t << std::endl;
    return t;
}

int main() {
    foo(10);
    foo(3.14);
    return 0;
}

模板的默认类型实参

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#include <iostream>
#include <type_traits>

template <typename T, typename = std::enable_if_t<std::is_integral<T>::value, bool>>
void foo(T t) {     // 只有需要一个版本的 foo 的情况下。因为模板的默认实参不同的两个模板是相同的东西。
                    // 如果想要两个版本以上, 则将 enable_if 做成模板类型, 请继续向下看。
  std::cout << "Integer: " << t << std::endl;
}

int main() {
  foo(10);
  return 0;
}

模板类型形参

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <type_traits>

/* 如果需要两个以上版本的 foo 的情况下。*/

template <typename T, std::enable_if_t<std::is_integral<T>::value, bool> = true>
void foo(T t) {     
  std::cout << "Integer: " << t << std::endl;
}

template <typename T, std::enable_if_t<std::is_floating_point<T>::value, bool> = true>
void foo(T t) {     
  std::cout << "Float: " << t << std::endl;
}

int main() {
  foo(10);
  foo(10.1);
  return 0;
}

模板的特化形参

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include <type_traits>

template<typename T, typename U>
class Foo {};

template<typename T>
class Foo<T, std::enable_if_t<std::is_same_v<T, int>, T>> {
  public:
    Foo() {
      std::cout << "int" << std::endl;
    }
};

template<typename T>
class Foo<T, std::enable_if_t<std::is_same_v<T, float>, T>> {
  public:
    Foo() {
      std::cout << "float" << std::endl;
    }
};

template<typename T>
using MyFoo = Foo<T, T>;

int main() {
  MyFoo<int> foo1;
  MyFoo<float> foo2;
  return 0;
}

扩展 enable_if

IsIntegral:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
template <typename...>
struct IsIntegral;
template <typename T>
struct IsIntegral<T> : std::is_integral<T> {};
template <typename First, typename... Rest>
struct IsIntegral<First, Rest...>
    : std::integral_constant<bool, IsIntegral<First>::value &&
                                       IsIntegral<Rest...>::value> {};

template <typename... Types>
using EnableIfIntegral =
    typename std::enable_if<IsIntegral<Types...>::value>::type;

IsIntegral<T, ...> 的作用是 enable_if 相同 (控制编译器是否生成相应的代码), 只是可以判断多个类型是否都是整数。See ref

References

0%