使用SFINAE检测静态constexpr

时间:2014-02-06 10:35:37

标签: templates c++11 g++ sfinae clang++

我试图从http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Member_Detector应用该技术来检查某个类型是否具有静态constexpr成员。

以下是我的尝试:

#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;
}

它适用于gcc:

$ g++  -std=c++11 test.cxx 
$ ./a.out 
1 
0

但是clang抱怨道:

$ 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
$

获取static constexpr地址的概念对我来说听起来不合适,所以我不会因为看到问题而感到沮丧。

那么,这样做的正确方法是什么?解决方案必须在gcc和clang中都有效。

0 个答案:

没有答案