C++ enable_if

本文探讨了C++中的is_integral_v用于判断类型是否为整型,is_same_v比较类型是否相同,以及enable_if实现基于类型条件的模板编译。通过实例演示了如何使用这些特性来创建UpperType函数,仅接受整数并转换为long long,展示了条件编译在模板设计中的实用价值。

目录

is_integral_v

is_same_v

enable_if

enable_if实现条件编译

应用示例:UpperType


is_integral_v

is_integral_v判断一个类型是不是整型

is_same_v

is_same_v判断两个类型是不是相同的类型

enable_if

enable_if就是通过模板偏特化实现重载,从而用来控制参数类型。

自定义版本:

template<typename T, bool flag>
struct enable {
	//
};
template<typename T>
struct enable<T, true> {
	typedef T type;
};

template<typename T>
typename enable < string, is_integral_v<T>>::type ToString(T t)
{
	return to_string(t);
}

int main()
{
	cout << ToString(123);
	//cout << ToString("123"); //编译失败
	return 0;
}

ToString函数只接受整数类型的参数,否则会编译报错type。

使用库的版本:

template<typename T>
typename enable_if<is_integral_v<T>, string>::type ToString(T t)
{
	return to_string(t);
}

int main()
{
	cout << ToString(123);
	//cout << ToString("123"); //编译失败
	return 0;
}

enable_if实现条件编译

template<typename T>
typename enable_if<is_same_v<T, string>, string>::type ToString(T t)
{
	return t;
}
template<typename T>
typename enable_if<!is_same_v<T, string>, string>::type ToString(T t)
{
	return to_string(t);
}

int main()
{
	cout << ToString(1234567890);
	cout << ToString(string("123"));
	return 0;
}

这个代码实现了,如果是string类型的参数就直接返回,否则就调用to_string函数再返回。

应用示例:UpperType

把整数类型变成long long,非整型不变

template<typename T, bool flag>
struct enable {
	typedef T type;
};
template<typename T>
struct enable<T, true> {
	typedef long long type;
};
#define UpperType(T) typename enable<T, is_integral_v<T>>::type

   	template<typename T>
	static UpperType(T) getSum(const vector<T>& v)
	{
		UpperType(T) ans = v[0];
		for (int i = 1; i < v.size(); i++)ans += v[i];
		return ans;
	}

C++ 模板编程中,`std::enable_if` 和 `std::enable_if_t` 是用于模板元编程的重要工具,主要用于在编译时根据条件启用或禁用特定的模板函数或类。它们之间的区别主要体现在语法和使用方式上。 ### `std::enable_if` `std::enable_if` 是一个模板结构体,其定义如下: ```cpp template<bool Condition, class T = void> struct enable_if; ``` 当 `Condition` 为 `true` 时,`enable_if<Condition, T>` 会定义一个类型 `type`,其类型为 `T`。如果 `Condition` 为 `false`,则 `enable_if` 不会定义 `type`,从而导致编译器在尝试访问 `type` 时产生错误。 通常情况下,`std::enable_if` 会与其他模板参数一起使用,以实现 SFINAE(Substitution Failure Is Not An Error)机制。例如: ```cpp template<typename T> typename std::enable_if<std::is_integral<T>::value, T>::type add(T a, T b) { return a + b; } ``` 在这个例子中,只有当 `T` 是整数类型时,`std::is_integral<T>::value` 才为 `true`,此时 `std::enable_if` 会定义 `type`,从而使该函数模板有效。否则,该函数模板会被忽略。 ### `std::enable_if_t` `std::enable_if_t` 是 C++14 引入的一个别名模板,它是 `std::enable_if<Condition, T>::type` 的简化形式。其定义如下: ```cpp template<bool Condition, class T = void> using enable_if_t = typename std::enable_if<Condition, T>::type; ``` 通过使用 `std::enable_if_t`,可以简化代码并提高可读性。例如,上面的例子可以改写为: ```cpp template<typename T> std::enable_if_t<std::is_integral<T>::value, T> add(T a, T b) { return a + b; } ``` 在这个例子中,`std::enable_if_t` 直接返回 `T` 类型,而不需要显式地写 `typename std::enable_if<...>::type`。 ### 使用场景 1. **函数重载**:可以通过 `std::enable_if` 或 `std::enable_if_t` 来实现基于类型的函数重载。 2. **类模板特化**:可以在类模板中使用 `std::enable_if` 来根据条件选择不同的实现。 3. **编译时断言**:可以在编译时检查某些条件是否满足,从而避免运行时错误。 ### 示例代码 以下是一个使用 `std::enable_if_t` 的示例: ```cpp #include <type_traits> #include <iostream> template<typename T> std::enable_if_t<std::is_integral<T>::value, T> add(T a, T b) { return a + b; } template<typename T> std::enable_if_t<std::is_floating_point<T>::value, T> add(T a, T b) { return a * b; } int main() { std::cout << add(3, 4) << std::endl; // 输出 7 std::cout << add(3.0, 4.0) << std::endl; // 输出 12 return 0; } ``` 在这个示例中,`add` 函数根据传入的类型(整数或浮点数)选择不同的实现。 ### 总结 - `std::enable_if` 是一个模板结构体,适用于 C++11 及更早版本。 - `std::enable_if_t` 是 C++14 引入的别名模板,简化了 `std::enable_if` 的使用。 - 两者都可以用于实现 SFINAE 机制,但在 C++14 及以后版本中,推荐使用 `std::enable_if_t` 以提高代码的可读性和简洁性 [^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值