Путаница с вложенным пространством имен в VS 2012 - PullRequest
0 голосов
/ 03 сентября 2018

У меня проблема с довольно простым кодом в VS 2012. Я тестировал этот код на CentOS 7, Debian 8, 9, Fedora 25, 26, 27, 28 и Ubuntu 14.04, 16.04, 18.04, как с последней версией GCC, так и Clang компиляторы в официальных пакетах, а также на VS 2013, VS 2015, VS 2017. Работает.

Вот минимальная версия инкриминируемого кода:

file0.h

namespace B {
    enum bar {
        HELLO,
        WORLD
    };
}

file1.h

namespace A {
namespace B {
    // Some stuff
}
}

file2.h

#include "file0.h"

namespace A {
namespace C {

    template<::B::bar = ::B::HELLO> class foo {
        // Some stuff
    };    
}
}

main.cpp

#include <iostream>
#include "file0.h"
#include "file1.h"
#include "file2.h"

int main() {
    ::A::C::foo<> myFoo;
    // Some stuff
}

Этот код приводит к следующей ошибке компиляции на VS 2012:

ошибка C2039: 'bar': не является членом 'A :: B'

Поскольку мы находимся в пространстве имен ::A::C в file2.h (и, следовательно, в пространстве имен ::A) и запрашиваем пространство имен ::B, кажется, что VS 2012 игнорирует :: до B и ищет в текущем namespace ::A first. Так как он не находит bar в ::A::B, он просто выдает ошибку вместо поиска в областях более высокого уровня.

Учитывая следующий ответ о переполнении стека, в VS 2012, похоже, есть ошибка с разрешением пространства имен.

Мои вопросы:

Есть ли способ решить эту проблему без изменения имен пространств имен (для меня очень важно сохранить B в :: B и :: A :: B)? Например, использовать другой синтаксис для использования пространства имен или использовать пространства имен псевдонимов?

Примечание: код для воспроизведения ошибки был отредактирован (на самом деле он содержит третий файл file0.h по сравнению с моим исходным постом. Моя ошибка).

1 Ответ

0 голосов
/ 03 сентября 2018

Мне не удалось воспроизвести эту ошибку на visual 2013 и 2008. Кажется, это особая проблема в 2010 и 2012 годах.

Может быть, попробуйте typedef вне объявления пространства имен:

namespace B {
    enum bar {
        HELLO,
        WORLD
    };
}
typedef ::B::bar my_type;
namespace A {
    namespace B {

        template<my_type= ::B::WORLD> class foo {
        };

    }
}

int main(int argc, char* argv[])
{
    A::B::foo<> myFoo;
}
...