在现代 C++ 编程中,类型转换是一个常见的需求。为了简化这一过程,本文将使用模板和 SFINAE(Substitution Failure Is Not An Error)技术实现的类型转换助手代码。该代码定义了一个命名空间 cast_helper,其中包含多个重载的 do_cast 函数,能够根据不同的输入类型进行类型转换。
命名空间 cast_helper 包含多个模板函数 do_cast,这些函数通过不同的模板参数和 SFINAE 技术来实现类型安全的转换。
template<typename ret_t, typename param_t,
std::enable_if_t<std::is_convertible_v<std::decay_t<ret_t>, std::decay_t<param_t>>, int> = 0>
ret_t do_cast(param_t&& param) {
return static_cast<ret_t>(param);
}
这个重载的 do_cast 函数用于将可转换的类型 param_t 转换为目标类型 ret_t。使用 std::is_convertible_v 检查类型之间的转换关系,确保类型安全。
template<typename ret_t, typename param_t, std::enable_if_t<std::is_integral_v<std::decay_t<ret_t>>, int> = 0,
std::enable_if_t<std::is_convertible_v<const char*, std::decay_t<param_t>>, int> = 0>
ret_t do_cast(param_t&& param) {
return static_cast<ret_t>(std::stoll(param));
}
此重载专门处理将字符串转换为整数类型(如 int、long 等)。它使用 std::stoll 函数将字符串转换为 long long,然后再进行类型转换。
template<typename ret_t, typename param_t, std::enable_if_t<std::_Is_any_of_v<std::decay_t<ret_t>, float, double>, int> = 0,
std::enable_if_t<std::is_convertible_v<const char*, std::decay_t<param_t>>, int> = 0>
ret_t do_cast(param_t&& param) {
return static_cast<ret_t>(std::stod(param));
}
这个重载处理将字符串转换为浮点数类型(如 float、double)。它使用 std::stod 函数进行转换。
template<typename ret_t, typename param_t, std::enable_if_t<std::is_same_v<std::decay_t<ret_t>, long double>, int> = 0,
std::enable_if_t<std::is_convertible_v<const char*, std::decay_t<param_t>>, int> = 0>
ret_t do_cast(param_t&& param) {
return static_cast<ret_t>(std::stold(param));
}
此重载专门处理将字符串转换为 long double 类型,使用 std::stold 函数。
template<typename ret_t, typename param_t, std::enable_if_t<std::is_same_v<std::decay_t<ret_t>, std::string>, int> = 0>
ret_t do_cast(param_t&& param) {
return std::to_string(param);
}
这个重载处理将其他类型(如整数、浮点数等)转换为 std::string,使用 std::to_string 函数。
template<typename ret_t, typename param_t>
ret_t type_cast(param_t&& parm) {
return cast_helper::do_cast<ret_t, param_t>(std::forward<param_t>(parm));
}
type_cast 函数是用户接口,调用 cast_helper::do_cast 来执行实际的类型转换。它使用 std::forward 来保持参数的完美转发特性。
使用示例
以下是如何使用 type_cast 函数进行类型转换的示例:
#include
#include
#include
#include
#include
#include
namespace cast_helper
{
template<typename ret_t, typename param_t,
std::enable_if_t<std::is_convertible_v <std::decay_t<ret_t>, std::decay_t<param_t>>, int> = 0>
ret_t do_cast(param_t&& param) {
return static_cast<ret_t>(param);
}
template<typename ret_t, typename param_t, std::enable_if_t<std::is_integral_v<std::decay_t<ret_t>>, int> = 0,
std::enable_if_t<std::is_convertible_v <const char*, std::decay_t<param_t>>, int> = 0>
ret_t do_cast(param_t&& param) {
return static_cast<ret_t>(std::stoll(param));
}
template<typename ret_t, typename param_t, std::enable_if_t<std::_Is_any_of_v<std::decay_t<ret_t>, float, double>, int> = 0,
std::enable_if_t<std::is_convertible_v <const char*, std::decay_t<param_t>>, int> = 0>
ret_t do_cast(param_t&& param) {
return static_cast<ret_t>(std::stod(param));
}
template<typename ret_t, typename param_t, std::enable_if_t<std::is_same_v<std::decay_t<ret_t>, long double>, int> = 0,
std::enable_if_t<std::is_convertible_v <const char*, std::decay_t<param_t>>, int> = 0>
ret_t do_cast(param_t&& param) {
return static_cast<ret_t>(std::stold(param));
}
template<typename ret_t, typename param_t, std::enable_if_t<std::is_same_v<std::decay_t<ret_t>, std::string>, int> = 0>
ret_t do_cast(param_t&& param) {
return std::to_string(param);
}
}
template<typename ret_t, typename param_t>
ret_t type_cast(param_t&& parm)
{
return cast_helper::do_cast<ret_t, param_t>(std::forward<param_t>(parm));
}
int main() {
int intValue = type_cast<int>("42");
double doubleValue = type_cast<double>("3.14");
long double longDoubleValue = type_cast<long double>("2.718281828459");
std::string strValue = type_cast<std::string>(intValue);
std::cout << "intValue: " << intValue << std::endl;
std::cout << "doubleValue: " << doubleValue << std::endl;
std::cout << "longDoubleValue: " << longDoubleValue << std::endl;
std::cout << "strValue: " << strValue << std::endl;
return 0;
}
输出结果
intValue: 42
doubleValue: 3.14
longDoubleValue: 2.71828
strValue: 42
总结
本文使用了一个灵活的类型转换助手,利用 C++ 的模板和 SFINAE 技术实现了多种类型之间的安全转换。通过 type_cast 函数,用户可以方便地将不同类型的数据进行转换,增强了代码的可读性和可维护性。这种方法在处理用户输入、配置文件解析等场景中非常有用。