一、std::enable_if介绍
对于SFINAE(不清楚的可以翻一下以前的相关文章)开发者来说,std::enable_if是绕不开的一个小话题。在C++11至C++20间,其在模板的元编程中起到了重要的作用。不过在C++20后Cocepts可以实现更清晰更简单的方式。它的定义方式为:
template< bool B, class T = void >
struct enable_if;
从C++14起还提供了一个辅助的类型,用来更简单的元编程中使用:
template< bool B, class T = void >
using enable_if_t = typename enable_if<B,T>::type;
其实非常好理解,这个模板结构体的第一个参数是bool型,第二个默认是个void,就是说,第一个参数决定了是否启用第二个参数。其具体的实现可能为:
template<bool B, class T = void>
struct enable_if {
};
template<class T>
struct enable_if<true, T> {
typedef 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) {
} // 错误:无法被重载
};
正确的应该是:
#include <iostream>
using namespace std;
struct T {
enum {
int_t, float_t } m_type;
template <typename Integer, std::enable_if_t<std::is_integral_v<Integer>, int> = 0> T(Integer) : m_type(int_t) {
}
template <typename Floating, std::enable_if_t<std::is_floating_point_v<Floating>, int> = 0>
T(Floating) : m_type(float_t) {
} // OK
};
int main() {
int d = 0;
float dd = 0.0f;
T t(d);
T tt(dd);
return 0;
}
//其编译后为:
#include <iostream>
using namespace std;
struct T
{
enum
{
int_t,
float_t
};
enum (unnamed) m_type;
template<typename Integer, std::enable_if_t<std::is_integral_v<Integer>, int> = 0>
inline T(Integer)
: m_type{
int_t}
{
}
/* First instantiated from: insights.cpp:15 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
inline T<int, 0>(int)
: m_type{
int_t}
{
}
#endif
template<typename Floating,