1. 程式人生 > >C++ Programming Language中的narrow_cast實現

C++ Programming Language中的narrow_cast實現

cast 編譯過程 efi 如果 rem 用例 pow false CI

在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實現