代码之家  ›  专栏  ›  技术社区  ›  YSC

模板忽略[[节点卡]]属性

  •  6
  • YSC  · 技术社区  · 7 年前

    当应用于函数时, [[nodiscard]] 属性鼓励编译器在被丢弃的表达式(而不是强制转换为)中使用时发出警告。 void . 例子:

    [[nodiscard]] int callable_return_not_discardable(int n)
    { return n; }
    
    int main()
    {
        callable_return_not_discardable(0); // warning/error:
            // ignoring return value of 'int callable_return_not_discardable(int)',
            // declared with attribute nodiscard [-Wunused-result]
        (void) callable_return_not_discardable(0); // OK
    }
    

    现场演示 gcc-8 clang-7 .


    这很好,也很有用,直到添加了一个额外的间接层:模板:

    template<class Callable>
    void invoke_with_answer(Callable&& callable)
    { callable(42); }
    
    [[nodiscard]] int callable_return_not_discardable(int n)
    { return n; }
    
    int main()
    {
        invoke_with_answer(callable_return_not_discardable); // OK
    }
    

    现场演示 gcc-8 clang-7 .

    我的问题是:
    它是一个缺失的特性,是什么模板的结果,还是应该修复clang和gcc以在这里发出警告?

    2 回复  |  直到 7 年前
        1
  •  8
  •   StoryTeller - Unslander Monica    7 年前

    [[nodiscard]] 不是函数签名或类型的一部分,并且在将该函数转换为指针或绑定到引用时根本不保留。这正是您的示例所做的。

    无论出于何种目的,模板都不能“看到”属性。

        2
  •  2
  •   YSC    7 年前

    AS explained by StorryTeller , [[nodiscard]] 不是函数签名或类型的一部分,这就是模板正文上下文中信息丢失的原因。

    要传播该警告,一个解决方案是添加 [ [不丢弃] ] 该函数的返回类型的属性:

    template<class Callable>
    void invoke_with_answer(Callable&& callable)
    { callable(42); } // warning
    
    struct [[nodiscard]] Int { int value; };
    
    Int callable_return_not_discardable(int n)
    { return {n}; }
    
    int main()
    {
        invoke_with_answer(callable_return_not_discardable); // note
    }
    

    Live demo on gcc-8