滑蒻稽的博客

【笔记】enable_if 的使用

参见:

C++11 enable_if 的使用 - ouuan的博客

Effective C++ 42:typename 的两种用法 | Harttle Land

std::enable_if - cppreference.com

然后就可以写出这样的代码:

mt19937_64 rnd(chrono::steady_clock::now().time_since_epoch().count());
template<typename T, enable_if_t<is_integral<T>::value, bool> = 0>
T rd(T l, T r) { return uniform_int_distribution<T>(l, r)(rnd); }
template<typename T, enable_if_t<is_floating_point<T>::value, bool> = 0>
T rd(T l, T r) { return uniform_real_distribution<T>(l, r)(rnd); }

int main() {
	cout << rd(1, 10); // sample output: 7
	cout << rd(1.1, 3.3); // sample output: 1.25297
	
  return 0;
}

理解起来还是有点复杂的。首先 enable_if_t 是 C++14 加入的一个语法糖:

template< bool B, class T = void >
using enable_if_t = typename enable_if<B,T>::type;

这里 = 号后面的 typename 用来声明 enable_if<B,T>::type 是一个类型而不是变量,因为在使用模板的情况下编译器无法得知 enable_if<B,T>::type 是类型还是变量。你可能会问在调用模板的时候当然是知道它是类型还是变量的啊,但根据这里的解释,编译器在通过实际的调用来生成代码之前有一个对模板的解析(这样才能生成候选列表之类的吧)。

然后是不能写成这样:

struct T {
    enum { int_t,float_t } m_type;
    template <typename Integer,
              typename = std::enable_if_t<std::is_integral_v<Integer>>
    >
    T(Integer) : m_type(int_t) {}
 
    template <typename Floating,
              typename = std::enable_if_t<std::is_floating_point_v<Floating>>
    >
    T(Floating) : m_type(float_t) {} // 错误:不能重载
};

因为两个函数模板仅有缺省的参数不同,会被认为是同一个函数。

正确的写法利用模板的非类型参数,因为在函数模板等价规则里认为只有每个非类型的类型相同,两个函数模板才是等价的。

posted @ 2022-11-16 16:34  huaruoji  阅读(112)  评论(1编辑  收藏  举报