I'm trying to apply the technique from http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Member_Detector to check if a type has a static constexpr member.
Here is what I have tried:
#include <stddef.h>
#include <stdint.h>
#include <iostream>
struct Foo {
static constexpr uint32_t magic = 100;
};
struct Bar {
static constexpr uint32_t bla = 100;
};
template <class T>
class HasMember_magic {
private:
using Yes = char[2];
using No = char[1];
struct Fallback {
static constexpr uint32_t magic = 0;
};
struct Derived : T, Fallback {};
template <class U>
static No& test(decltype(U::magic)*);
template <typename U>
static Yes& test(U*);
public:
static constexpr bool RESULT =
sizeof(test<Derived>(nullptr)) == sizeof(Yes);
};
int main(int argc, char* argv[]) {
std::cout << HasMember_magic<Foo>::RESULT << std::endl;
std::cout << HasMember_magic<Bar>::RESULT << std::endl;
return 0;
}
It works fine with gcc:
$ g++ -std=c++11 test.cxx
$ ./a.out
1
0
But clang complains:
$ clang++ -std=c++11 test.cxx
test.cxx:32:24: error: call to 'test' is ambiguous
sizeof(test<Derived>(nullptr)) == sizeof(Yes);
^~~~~~~~~~~~~
test.cxx:37:22: note: in instantiation of template class 'HasMember_magic<Bar>' requested here
std::cout << HasMember_magic<Bar>::RESULT << std::endl;
^
test.cxx:25:20: note: candidate function [with U = HasMember_magic<Bar>::Derived]
static No& test(decltype(U::magic)*);
^
test.cxx:28:21: note: candidate function [with U = HasMember_magic<Bar>::Derived]
static Yes& test(U*);
^
1 error generated.
$ clang++ --version
clang version 3.4 (tags/RELEASE_34/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
$
The concept of taking the address of a static constexpr
does not sound right to me, so I'm not supprised by seeing problems.
So, what is the right way of doing this? The solution must work both in gcc and clang.