SFINAE和Clang vs. GCC与MSVC的能见度检查 - 这是正确的吗?

Meh*_*dad 7 c++ access-specifier sfinae template-meta-programming c++03

我写了一个与C++ 03兼容的实现的尝试is_default_constructible:

template<class = void> struct is_default_constructible;
template<> struct is_default_constructible<>
{
protected:
    // Put base typedefs here to avoid pollution
    struct twoc { char a, b; };
    template<bool> struct test { typedef char type; };
    template<class T> static T declval();
};
template<> struct is_default_constructible<>::test<true> { typedef twoc type; };
template<class T> struct is_default_constructible : is_default_constructible<>
{
private:
    template<class U> static typename test<!!sizeof(::new U())>::type sfinae(U*);
    template<class U> static char sfinae(...);
public:
    static bool const value = sizeof(sfinae<T>(0)) > 1;
};
Run Code Online (Sandbox Code Playgroud)

当我在GCC(-std=c++03)中测试它时,它返回,0因为构造函数是不可见的:

class Test { Test(); };

int main()
{
    return is_default_constructible<Test>::value;
}
Run Code Online (Sandbox Code Playgroud)

当我在Visual C++中测试它时(不同的版本都有相同的行为),我回来了1.

当我在Clang(也-std=c++03)中测试时,我得到:

error: calling a private constructor of class 'Test'
template<class U> static typename test<!!sizeof(::new U())>::type sfinae(U *);
                                                      ^
note: while substituting explicitly-specified template arguments into function template 'sfinae' 
static bool const value = sizeof(sfinae<T>(0)) > 1;
                                 ^
note: in instantiation of template class 'is_default_constructible<Test>' requested here
return is_default_constructible<Test>::value;
       ^
error: calling a private constructor of class 'Test'
template<class U> static typename test<!!sizeof(::new U())>::type sfinae(U *);
                                                      ^
note: while substituting deduced template arguments into function template 'sfinae' [with U = Test]
static bool const value = sizeof(sfinae<T>(0)) > 1;
                                 ^
note: in instantiation of template class 'is_default_constructible<Test>' requested here
return is_default_constructible<Test>::value;
Run Code Online (Sandbox Code Playgroud)

哪个编译器是正确的,为什么?

Dav*_*eas 0

该代码不是有效的 C++03,尽管它是有效的 C++11。g++ 4.8 编译器遵守 C++11 规则并忽略 SFINAE 上下文中不可访问的成员,而 clang 编译器遵守 C++03,其中找到并选择成员(本例中的构造函数),但进行访问检查使代码无效。VS(无论您使用什么版本)都不遵守 C++11 或 C++03 规则,它似乎完全忽略了内部的访问说明符sizeof