在C++中,各种数值类型的转化是C++编译过程中警告的主要来源,但是,很多时候,我们需要使用各种数值类型,例如我们用数组的某一位表示大小为对应序号的值,这种情况下,经常会涉及多种数值类型。根据C++ Programming Language中的建议,在数值类型转换时,使用narrow_cast来实现运行时安全,这里给出C++14版本的实现。
// there is no implicit conversion from Source to Target template <typename Target, typename Source, typename = std::enable_if_t< !std::is_same<std::common_type_t<Target, Source>, std::decay_t<Target>>::value>> inline Target narrow_cast(Source v) { static_assert(!std::is_reference<Target>::value, "The target couldn‘t be reference"); static_assert(std::is_arithmetic<Source>::value, "The parameter of narrow_cast should be arithmetic"); static_assert(std::is_arithmetic<Target>::value, "The return value of narrow_cast should be arithmetic"); // using Target_U = std::remove_reference_t<Target>; // using Source_U = std::remove_reference_t<Source>; auto r = static_cast<Target>(v); if (static_cast<Source>(r) != v) throw std::runtime_error("narrow_cast<>() failed"); return r; } // there is implicit conversion from Source to Target template <typename Target, typename Source, typename = std::enable_if_t< std::is_same<std::common_type_t<Target, Source>, std::decay_t<Target>>::value>> inline constexpr std::remove_reference_t<Source> narrow_cast(Source v) { static_assert(!std::is_reference<Target>::value, "The target couldn‘t be reference"); static_assert(std::is_arithmetic<Source>::value, "The parameter of narrow_cast should be arithmetic"); static_assert(std::is_arithmetic<Target>::value, "The return value of narrow_cast should be arithmetic"); return static_cast<Target>(v); }
下面给出,使用Catch写的简单测试用例:
#define CATCH_CONFIG_MAIN #include "catch.hpp" #include <cmath> TEST_CASE("Test narrow_cast", "[narrow_cast]") { int i = 10; long long j = 15; long long& k = j; REQUIRE(narrow_cast<long>(k) == 15); REQUIRE(narrow_cast<long>(i) == 10); long long very_big = pow(10, 12); bool exception = false; try { narrow_cast<long>(very_big) == very_big; } catch (const std::runtime_error& error) { exception = true; } REQUIRE(exception); //REQUIRE(narrow_cast<long&>(k) == 15); //REQUIRE(narrow_cast<long&>(i) == 10); }
测试可知,在转化的类型可以容纳时,narrow_cast可以正常运行,如果narrow_cast转化后的值与原值不同时,会抛出runtime_error的异常。
C++ Programming Language中的narrow_cast实现
原文:https://www.cnblogs.com/albizzia/p/9190247.html