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

标签 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说明符将隐式声明该函数内联,这需要在评估时定义。不过,该函数并未在我的代码中使用 - 但是 clang 会发出该警告(表示编译器中存在小问题)。当 constexpr 时,clang 将不再发出此警告。省略了说明符。 constexpr无论如何,说明符似乎都不合适,(感谢 @Yakk )。

    最佳答案

    备注 ;如前所述,clang 发出的诊断仅仅是警告而不是错误,这意味着它只是为了吸引我们注意如果处理不当可能会被误用的部分。

    什么可能会出错?

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

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

    [dcl.fct.spec]

    4) An inline function shall be defined in every translation unit in which it is odr-used and shall have exactly the same definition in every case (3.2).




    [basic.def.odr]

    2) An expression is potentially evaluated unless it is an unevaluated operand (Clause 5) ...

    3) A variable x whose name appears as a potentially-evaluated expression ex is odr-used ...

    4) ... An inline function shall be defined in every translation unit in which it is odr-used and shall have exactly the same definition in every case (3.2).




    clang 是否正确发布 -Wundefined-inline在我们的背景下?

    技术上... ,警告没有值(value),因为我们使用了 select在未评估的上下文中不违反一个定义规则。

    您可以通过传递 -Wno-undefined-inline 来抑制警告。在调用 clang 时,如果这让你很困扰,请 file a bug report .

    关于templates - 带有函数调用表达式的 `decltype` 何时需要定义函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22016495/

    相关文章:

    与枚举匹配的模板函数中的 C++ 无法解释的变化

    c++ - 调用模板参数 constexpr 方法?

    c - 为什么我的程序没有打印正确的值?

    c++ - 如何在派生类中初始化基类静态内联数据成员?

    c++ - 在 C++ 类中构造自定义模板

    c++ - 使用命名空间作为模板参数的替代方法

    c++ - `xvalue` C++11/14 中的行为

    c++ - 迭代器不会遍历整个 map

    c++ - 使用 cmake、clang 和 llvm 为 visual studio 构建工具链

    c++ - 没有用于初始化 'string'(又名 'basic_string<char>')的匹配构造函数