И снова время пятничного зачила. Наливайте пивка, открывайте последний драфт стандарта C++23 (N4950) и поехали.



Рассмотрим вот такой пример, обозначим его [1].



class X {

template <typename U> struct Hidden {};

};



template <typename T>

using Wrapper = typename X::template Hidden<T>;



int main() {

Wrapper<float> w;

}




https://godbolt.org/z/sMnec5nx4



В нём clang и gcc почему-то не выдают ошибок, хотя имя является скрытым. Тут хочется воскликнуть — ну наверное по стандарту открытость using зависит от него а не от того что он алиасит. Не торопитесь, читайте дальше.



Уберём шаблоны и получим пример [2].



class X {

struct Hidden {};

};



using Wrapper = typename X::Hidden;



int main() {

Wrapper w;

}




https://godbolt.org/z/q9TYMeaYo



Вроде он мало чем отличается, тоже using, но тут оба компилятора отказываются компилировать.



Теперь пойдём от [1] в другом направлении: заменим using на struct и получим пример [3].



class X {

template <typename U> struct Hidden {};

};



template <typename T>

struct Wrapper : X::template Hidden<T> {};



int main() {

Wrapper<int> w;

}




https://godbolt.org/z/Gs1s3z8qn



Оба компилятора отказываются компилировать. То есть using всё-таки важен? Ситуация становится интересней.



И теперь сделаем последний шаг: запишем пример [3], но не будем инстанцировать шаблон (т.е. уберём функцию main) и получим пример [4].



https://godbolt.org/z/9EM1avbxe



И внезапно тут мнения компиляторов расходятся. Clang выдаёт ошибку, тогда как gcc отлично компилирует.



Вопросы:

1. Обоснуйте с точки зрения стандарта чем отличается [1] от [2]

2. Обоснуйте с точки зрения стандарта чем отличается [1] от [3]

3. Обоснуйте с точки зрения стандарта какой из компиляторов прав в [4]?



Ответы кидайте в комментарии к посту. Ссылки на нормативные документы обязательны.



Призов не обещаю (кроме зрительских симпатий). Рекомендуется сначала подумать самостоятельно, потом заезжать в комментарии.



#questions