Benjamin Barrois
Benjamin Barrois

Reputation: 2686

Nested namespace confusion with VS 2012

I have a problem with quite a simple code with VS 2012. I tested this code on centOS 7, Debian 8, 9, Fedora 25, 26, 27, 28 and Ubuntu 14.04, 16.04, 18.04 both with the latest GCC and Clang compilers in the official packages, and on VS 2013, VS 2015, VS 2017. It works.

Here is a minimum version of the incriminated code:

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
}

This code leads to the following compilation error on VS 2012:

error C2039: 'bar' : is not a member of 'A::B'

As we are in namespace ::A::C in file2.h (and therefore in namespace ::A) and asking for namespace ::B, it seems that VS 2012 ignores the :: before B and searches in current namespace ::A first. As it does not find bar in ::A::B, it just throws an error instead of searching in higher-level scopes.

Given the following answer on Stack Overflow, there seem to be a bug in VS 2012 with namespace resolution.

My questions are:

Is there a way to solve this problem without changing the names of namespaces (it is very important to me to keep B in ::B and ::A::B)? Like using an other syntax for namespace usage, or using alias namespaces?

Note: the code for bug reproduction was edited (it actually involves a third file file0.h compared to my original post. My mistake).

Upvotes: 2

Views: 116

Answers (1)

PilouPili
PilouPili

Reputation: 2699

I was not able to reproduce this bug on visual 2013 and 2008. It seems to be a specific problem in 2010 and 2012.

Maybe try a typedef outside the namespace declaration:

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;
}

Upvotes: 1

Related Questions