【发布时间】:2016-08-17 13:18:00
【问题描述】:
我正在使用一个简单的 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()");
(我现在知道there’s a simpler method,但是当我写这段代码时还没有回来。)
此代码适用于 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 的错误吗?还是抱怨是对的?如果是这样,GCC 是否也正确地接受了这个代码?
此外,在写这个问题时,我意识到可以通过删除成员函数模板前面的constexpr 限定符来完全避免clang 编译错误。 constexpr 的存在在这里有什么变化?
1 这是一个问题,因为我正在使用 -Werror 进行编译。有一些警告是基于启发式的,因此存在不可避免的误报,但据我所知,情况并非如此。
【问题讨论】: