SFINAE и проверка видимости в Clang против GCC против MSVC — что правильно?

Я написал свою попытку 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;
};

Когда я проверю это в GCC (-std=c++03), это возвращает 0 потому что конструктор невидим:

class Test { Test(); };

int main()
{
return is_default_constructible<Test>::value;
}

Когда я тестирую его в 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;

Какой компилятор правильный и почему?

7

Решение

Код не является допустимым C ++ 03, хотя он действителен C ++ 11. Компилятор g ++ 4.8 соблюдает правила C ++ 11 и игнорирует недоступные члены в контексте SFINAE, в то время как компиляторы clang соблюдают C ++ 03, где элемент (конструктор в данном случае) найден и выбран, но проверяется доступ сделать код недействительным. VS (какую бы версию вы не использовали) не соответствует правилам C ++ 11 или C ++ 03, похоже, он игнорирует спецификатор доступа внутри sizeof полностью.

0

Другие решения


По вопросам рекламы ammmcru@yandex.ru
Adblock
detector