• C++ Programming Language中的narrow_cast实现


    在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# XmlSerializer实现序列化浅析(转载)
    Direct3D学习(资料收集)
    幸福法则
    javascript中的keydown事件中的参数问题
    去除UTF8 BOM【转】
    JavaScript常用资料参考
    KCFinder CKEditor的文件管理器插件
    elFinder Web文件管理器
    用TcpTrace调试Web服务器
    Ubuntu 12.04如何登入root?
  • 原文地址:https://www.cnblogs.com/albizzia/p/9190247.html
Copyright © 2020-2023  润新知