是否有解决方法从另一个命名空间内定义成员?

时间:2014-10-22 20:05:10

标签: c++ templates c++11 namespaces

这可能看起来有点深奥,但我有一个这样的类结构,其中单个模板类定义在与实际使用它的类不同的命名空间中。

namespace F{
    template<typename>
    struct Foo{
        static Foo instance;
    };
}

namespace B{
    struct Bar{};
    F::Foo<Bar> F::Foo<Bar>::instance; //error C2888
}

哪个收益率:

error C2888: 'Foo<void> Foo<void>::instance' : symbol cannot be defined within namespace 'B'

我知道这就是它应该是的样子,但在我的实例Foo是我的库的一部分,而Bar是由客户定义的,所以他们赢了&#39;必须是同一名称空间的一部分。定义Foo<void>::instance的部分是宏的一部分,因此我可以隐藏用户的复杂性。

是否有任何方法可以让我从另一个命名空间内定义一个类的成员?

1 个答案:

答案 0 :(得分:4)

针对您的特定需求的简单解决方案(假设所提供的示例代码是相关的)是使用Meyers' singleton,例如

namespace F{
    template<class>
    struct Foo{
        static auto instance() -> Foo& {
            static Foo the_instance;
            return the_instance;
        }
    };
}

或者,您可以在头文件中提供静态成员的一般定义,由于ODR中模板的特殊豁免,该定义正常工作:

namespace F{
    template<class>
    struct Foo{
        static Foo instance;
    };

    template<class Type>
    Foo<Type> Foo<Type>::instance;
}

<强>修订

这是最后一种方法的具体例子。它适用于g ++ 4.8.2和Visual C ++ 12.0(2013)。我记不起早期编译器版本的任何问题。

的main.cpp
auto main() -> int {}
x.h
#pragma once

namespace F{
    template<class>
    struct Foo{
        static Foo instance;
    };

    template<class Type>
    Foo<Type> Foo<Type>::instance;
}
a.cpp
#include "x.h"

#include <iostream>

struct A {};
static bool u = !(std::cout << "A " << &F::Foo<A>::instance << std::endl);

#include "x.h"
a2.cpp
#include "x.h"

#include <iostream>

struct A {};        // Intentionally same as in file "a.cpp"
static bool u = !(std::cout << "A " << &F::Foo<A>::instance << std::endl);
b.cpp
#include "x.h"

#include <iostream>

struct B {};
static bool u = !(std::cout << "B " << &F::Foo<B>::instance << std::endl);

使用Visual C ++构建和运行:

H:\dev\test\so\0169>cl main.cpp a.cpp a2.cpp b.cpp /Feb
main.cpp
a.cpp
a2.cpp
b.cpp
Generating Code...

H:\dev\test\so\0169>b
A 00988A50
A 00988A50
B 00988A6E

H:\dev\test\so\0169>_