Поиск имен в шаблонном классе

Какие определения должны использоваться в шаблонном классе, в случае, если возникает неоднозначность между именем шаблонного параметра и типом, определенном в базовом классе зависимом от шаблонного параметра?

MSVC и G++ ведут себя по разному. Кто прав и почему?

Пример: https://godbolt.org/z/1Efa9zvEs

#include <type_traits>

struct S1
{};

struct S2 : S1
{
    using Base=S1;
};

template<typename Base>
struct Wrap : Base
{
    using base=Base;
};

static_assert( std::is_same_v< Wrap<S2>::base, S2 > ); // g++ - ok, msvc - fail
static_assert( std::is_same_v< Wrap<S2>::base, S1 > ); // msvc - ok, g++ - fail

Ответы (1 шт):

Автор решения: isnullxbh

В определении:

template<typename Base>
struct Wrap : Base
{
    using base = Base;
};

шаблонный параметр Base вводит имя Base в пространство имен класса Wrap. Соответственно, когда мы объявляем type alias:

using base = Base;

, Base не может быть ничем иным, как типом, которым параметризуется Wrap при инстанцировании. И раз мы инстанцируем его с S2, то Base - это S2.

C моей точки зрения прав g++.


UPD.: в более свежей версии компилятора MSVC static_assert фэйлится.

→ Ссылка