2016-11-18 5 views
2

Предположим, что мы имеем такую ​​структуру:Кто здесь, GCC или MSVC?

namespace some_namespace::types { 
    using foo_t = int; 
} 

namespace some_namespace::classes { 
    class bar { 
    public: 
     auto do_stuff() -> types::foo_t; 
    }; 
} 

using namespace some_namespace::classes; 

auto bar::do_stuff() -> types::foo_t { 
    return 1; 
} 

Этот код компилируется счастливо в GCC6.
С другой стороны, VS15 с включенным переключателем /std:c++latest не распознает тип возврата do_stuff. Он возвращает C2653.

Теперь, что я нахожу весьма подозрительным, что это фиксируется путем изменения во второй половине этого:

using namespace some_namespace; 

auto classes::bar::do_stuff() -> types::foo_t { 
    return 1; 
} 

, который в моих глазах должны быть равны. Я ошибаюсь, думая, что это ошибка MSVC? Что говорит об этом стандарт?

+1

Непосредственно GCC и MSVC внедряют новый стандарт с разной скоростью и с разными приоритетами. –

+0

Я думаю, что GCC просто становится более снисходительным. – Arunmu

+0

Поддержка MSVC C++ 17: https://msdn.microsoft.com/en-us/library/hh567368.aspx –

ответ

4

Это не имеет никакого отношения к функции C++ 17, которая не касалась директив, а не вообще с помощью директив. MSVC производит ту же ошибку от

namespace some_namespace{ 
    namespace types { 
     using foo_t = int; 
    } 
    namespace classes { 
     class bar { 
     public: 
      auto do_stuff() -> types::foo_t; 
     }; 
    } 
} 

using some_namespace::classes::bar; 

auto bar::do_stuff() -> types::foo_t { 
    return 1; 
} 

[basic.lookup.unqual]/8:

Для членов класса X, имя, используемое [...] в определении члена класса вне определения X после описателя-И.Д. члена, должен быть объявлен в одном из следующих способов:

  • перед его использованием в блоке, в котором он используется или в качестве вмещающего блока ([stmt.block]), или

  • должен быть членом класса X или быть членом базового класса X ([class.member.lookup]), или

  • [... две пули точки о вложенных и локальные классы опущено ...]

  • , если X является членом пространства имен N [.. .], перед использованием имени, в пространстве имен N или в одном из N Входящие пространства имен.

Имя поиска для types должны сначала заглянуть внутрь bar, то внутри classes, то внутри some_namespace. Это последнее должно найти пространство имен types.