【问题标题】:How to predicate on something having a signed numeric type?如何断言具有带符号数字类型的东西?
【发布时间】:2013-12-14 15:09:03
【问题描述】:

假设我有一些执行以下操作的模板代码:

T x = foo();
T y = -x;

现在,如果 T 是非数字类型(或者没有实现一元减号),编译将简单地失败。但如果它是 unsigned int、unsigned short 等,它会成功,但会发出警告。所以我希望能够做到

T x = foo();
if (/* magic condition */ {
    T y = -x;
}

我可以写出 T 的类型是某种有符号数字类型的条件(在编译时或运行时检查)吗?例如使用 typeid?

注意:

  • 断言也不错,但我想要更灵活的东西。

【问题讨论】:

    标签: c++ polymorphism conditional-compilation typeof typeid


    【解决方案1】:

    C++11 具有 is_unsigned 特征,您可以在 static_assert 中使用它:

    #include <type_traits>
    
    template <typename T>
    void foo()
    {
        static_assert(std::is_unsigned<T>::value);
    
        T x = /* ... */
        T y = -x;
    
        /* ... */
    }
    

    如果您需要更动态的检查,只需将其粘贴在 if 条件中即可:

    template <typename T>
    void foo()
    {
        if (!std::is_unsigned<T>::value) {
            /* To arrive here and for the following
               not to error out, we must have a numeric
               type that's not unsigned! */
    
            T x = /* ... */
            T y = -x;
        }
        else {
           /* Do something else for unsigned numeric
              types */
        }
    }
    

    更复杂的解决方案涉及重载、std::enable_if 和各种其他模板元黑客,但以上可能就是您所需要的。

    【讨论】:

    • 您能否更新您的答案以解决我的澄清问题?
    • @einpoklum Huh,谁会想到当你需要一个动态分支时你会使用 if :)。
    • @einpoklum:你得到答案了吗?
    • 好吧,部分原因是,因为谓词不会为我保存一个编译器警告,即在此条件包围的块中类型转换为/从无符号。
    • 然后回到标签调度。
    【解决方案2】:

    是的,你可以。

    static_assert(std::is_unsigned<T>::value, "Not unsigned!");  
    

    (您需要包含 type_traits 才能使其工作。)

    然后,您可以自然地调整编译过程,如果您确定没有其他方法,甚至可以使用 enable_if :)。

    【讨论】:

    • 我想要一个if (...),而不是一个断言。将澄清我的问题。
    • @einpoklum 然后使用标签调度。虽然我不确定你会在 else 的情况下做什么(好吧,这个警告首先是完全愚蠢的,因为无符号减号是完全明确定义的)。
    • @ChristianRau:你的意思是,就像here?
    • @einpoklum 是的,它接缝了。您基本上使用附加参数 void foo_impl(..., std::true_type)void foo_impl(..., std::false_type) (或任何您的实际方法签名)创建两个重载方法,然后从您调用所需的主方法中,让 std::is_unsigned&lt;T&gt; 进行重载选择(因为它来自std::true_typestd::false_type):void foo(...) { foo_impl(..., std::is_unsigned&lt;T&gt;()); }。 (当然,这些点是占位符,而不是实际的点)。
    • TBH 一个简单的if (std::is_unsigned&lt;T&gt;::value) 可能是我们想要的。编译器几乎肯定会对其进行优化。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-01
    • 2011-08-14
    • 2017-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多