Clang抱怨在未求值的上下文中没有定义constexpr函数
Clang complains about undefined constexpr function in unevaluated context
我使用一个简单的SFINAE技巧来检查成员函数是否存在,如下所示:
#include <type_traits>
template <typename C>
struct has_size {
template <typename T>
static constexpr auto check(T*) ->
decltype(std::declval<T const>().size(), std::true_type{});
template <typename>
static constexpr auto check(...) -> std::false_type;
static constexpr bool value = decltype(check<C>(nullptr))::value;
};
// Usage:
static_assert(has_size<std::vector<int>>::value, "std::vector<int> has size()");
(我知道现在有一个更简单的方法,但是在我写这段代码的时候还没有)
此代码适用于GCC。Clang发出一个警告1(所有版本到Apple LLVM 7.3,以上游为准):
decltype.cpp:15:27: error: inline function 'has_size<std::__1::vector<int, std::__1::allocator<int> > >::check<std::__1::vector<int, std::__1::allocator<int> > >' is not defined [-Werror,-Wundefined-inline]
static constexpr auto check(T*) ->
^
decltype.cpp:22:44: note: used here
static constexpr bool value = decltype(check<C>(nullptr))::value;
换句话说,clang期望函数被定义,而不仅仅是声明,即使它们从未被调用(仅在decltype
的未求值上下文中)。
这是clang中的一个bug吗?或者抱怨是对的吗?如果是这样,GCC接受这个代码也是正确的吗?
此外,在编写这个问题时,我意识到可以通过删除成员函数模板前面的constexpr
限定符来完全避免clang编译错误。这里constexpr
的存在改变了什么?
1这是一个问题,因为我正在编译-Werror
。有一些警告是基于启发式的,因此不可避免地会出现误报,但就我所知,这里的情况并非如此。
如果你不打算调用一个函数,那么把它标记为constexpr
是没有意义的。
constexpr
对类型系统是不可见的(好吧,除了c++ 14之前的版本,它的副作用是创建了一个非静态成员函数const
);相反,它承诺,对于模板类型参数和函数参数(以及对象状态,对于非静态成员函数)的至少一个组合,函数体可以作为常量表达式(或等效于常量表达式的算法)对求值。相反,函数上缺少constexpr
是对编译器的指令,甚至不要尝试将函数体作为常量表达式求值。
Clang不是正确的,确切地说,但它也不是不正确的,因为您已经明确要求它拒绝有效的程序(使用-Werror
)。您应该将警告错误视为一个强烈的暗示,即没有定义的constexpr
函数是一个坏主意。
这是clang中的一个bug吗?或者抱怨是对的吗?如果是这样,GCC也是正确的吗接受这个代码?
此外,在写这个问题的时候,我意识到clang编译通过删除前面的
constexpr
限定符可以完全避免错误成员函数模板的。constexpr
的存在改变了什么在这里吗?
编译器警告在c++标准之外。对包含人为错误指示的有效程序发出警告。在您的特殊情况下,您选择使用constexpr
来限定没有定义的函数。使用该类的程序只有在不调用该函数的情况下才有效。如果真的是这样,那么constexpr
就不需要了。但是,如果您打算调用该函数(尽管忘记提供它的实现),但由于某些错误(复杂的重载解析,或者只是一个愚蠢的打字错误),调用了不同的函数,该怎么办?
因此Clang发出警告是有其意义的。然而,这种情况是否值得警告是有争议的;
- 在命名空间中定义函数还是限定函数
- 为什么在定义函数之前先声明它
- 使用用户定义函数的字符串反转
- 用户定义函数中的指针和输入
- 这个c++代码是如何在没有定义函数的情况下运行的
- 具有外部"c"和程序集的未定义函数
- 已定义函数时出现 G++ "未定义的引用"错误
- 将自定义函数传递到基抽象类中以延迟执行
- C++使用 rand 定义函数语法
- Arduino:在 loop() 和自定义函数中运行相同的代码时出现问题
- 将具有固定签名的自定义函数名称注入 CRTP
- 使用定义函数模板别名
- 是否可以使用单个定义定义函数的常量和常规版本?(使用模板,自动,decltype等)
- 在内联程序集中定义函数和从 C++ 调用时出现问题
- 在 Metal 着色器代码中,如何定义函数的 in/out 参数变量?
- 声明和定义函数静态会产生"undefined reference to function_name()"
- 朋友定义函数的名称空间是什么
- 介子 对用户定义函数的未定义引用
- 如何使用 "using" 关键字定义函数原型/签名
- 在 C 结构中定义C++函数