函数调用表达式的"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说明符将隐式声明该函数内联,这需要在对其求值时进行定义。不过,我的代码中没有使用函数,但clang会发出警告(表示编译器中有一个小问题)。当省略constexpr说明符时,clang将不再发出此警告。constexpr说明符似乎无论如何都不合适(感谢@Yakk)。

注意;如前所述,clang发布的诊断只是一个警告,而不是一个错误,这意味着它只是为了吸引我们的注意力,如果处理不当,可能会被滥用


可能出现的问题是什么

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

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

[dcl.fct.spec]

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

[basic.def.odr]

2)表达式可能被求值,除非它是未求值的操作数(第5条)。。。

3) 变量x的名称显示为可能求值的表达式ex,该变量被odr使用。。。

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


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

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

您可以在调用clang时通过传递-Wno-undefined-inline来抑制警告,如果这让您非常困扰,请提交错误报告。

最新更新