带有函数调用表达式的`decltype`何时需要定义函数?

时间:2014-02-25 14:03:26

标签: templates c++11 clang sfinae decltype

在clang中我得到了这个警告

warning: inline function 'detail::selector<2, int>::select' is not defined [-Wundefined-inline]
    static constexpr auto select(T const&) -> std::integral_constant<int, Which>;
                          ^

note: used here
static_assert( decltype(Selector::select(int()))::value == 2, "");
                                  ^

在下面的代码中。

这里没有定义有害的功能吗? (我坚信,在我的应用程序中并不重要,因为它在未评估的上下文中使用,在std :: enable_if中)。

现在,我想知道 编译器认为它应该发出警告。

#include <type_traits>

namespace detail {

    template <int Which, typename...> struct selector;

    template <int Which>
    struct selector<Which> {
        static constexpr void select();  // never select
    };

    template <int Which, typename T, typename... Ts>
    struct selector<Which, T, Ts...> : selector<Which+1, Ts...>
    {
        using selector<Which+1, Ts...>::select;
        static constexpr auto select(T const&) -> std::integral_constant<int, Which>;
    };
}

int main(int argc, const char * argv[])
{
    using Selector = detail::selector<0, char, short, int>;
    static_assert( decltype(Selector::select(int()))::value == 2, "");    
    return 0;
}

编辑:

注意:

  • ideone.com上的gcc-4.8.1不会发出警告。

  • 摆脱警告的最简单方法是提供一种实现,例如:

    static constexpr auto select(T const&) 
    -> std::integral_constant<int, Which> 
    { return {}; }
    

    (谢谢@Yakk)


解决方案

正如@Filip Roséen提供的答案中所解释的那样,constexpr说明符将隐式声明函数内联,这需要在评估时定义。但是,我的代码中的函数 - 但是仍然会发出警告(表示编译器中的一个小问题)。当constexpr说明符被省略时,clang将不再发出此警告。 constexpr说明符似乎不合适(感谢@Yakk)。

1 个答案:

答案 0 :(得分:1)

注意;如上所述, clang 发出的诊断只是一个警告,而不是一个错误,这意味着它只是吸引我们注意一个如果处理不当可能会被误用的段。 < / p>


可能出现什么问题?

标记为 constexpr 的实体隐式inline(对于直接在类中定义的函数也是如此),如[dcl.fct.spec]p3中所述。

具有inline说明符的函数,无论是否隐式,都必须遵循应用于此类的规则。 clang 发出的警告是为了警告开发人员编写违反以下内容的代码(其中包括):

  

[<强> dcl.fct.spec

     
    

4)内联函数应在每个 odr-used 的翻译单元中定义,并且在每种情况下都应具有完全相同的定义(3.2)。

  

  

[<强> basic.def.odr

     
    

2)表达式可能被评估,除非它是未评估的操作数(第5条)......

         

3)变量x的名称显示为可能已评估的表达式ex odr-used ...

         

4)......内联函数应在每个 odr-used 的翻译单元中定义,并且在每种情况下都应具有完全相同的定义(3.2)。

  

在我们的上下文中发出-Wundefined-inline是否正确?

技术上...... ,警告没有任何价值,因为我们在未评估的上下文中使用select并未违反一个定义规则

您可以在调用 clang 时传递-Wno-undefined-inline来抑制警告,如果这让您感到困扰,请file a bug report