I’m using a simple SFINAE trick to check whether a member function exists, like so:
#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()");
(I’m aware that there’s a simpler method now, but wasn’t back when I wrote this piece of code.)
This code works on GCC. Clang however issues a warning1 (all versions up to Apple LLVM 7.3, whichever that is upstream):
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;
In other word, clang expects the functions to be defined, not just declared, even though they are never called (only in the unevaluated context of decltype
).
Is this a bug in clang? Or is it right to complain? If so, is GCC also correct in accepting this code?
Furthermore, while writing this question I realised that the clang compilation error can be avoided altogether by removing the constexpr
qualifier in front of the member function template. What does the presence of constexpr
change here?
1 Which is a problem as I’m compiling with -Werror
. There are some warnings that are based on heuristics and therefore have unavoidable false positives, but this isn’t the case here as far as I can see.