简体   繁体   English

是否有一种解决方法可以从另一个名称空间内部定义成员?

[英]Is there a workaround to define a member from inside another namespace?

This may seem a bit esoteric, but I have a class structure like this, where a singleton template class is defined in a different namespace than the class actually using it. 这似乎有些深奥,但是我有一个这样的类结构,其中单例模板类是在与实际使用它的类不同的名称空间中定义的。

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

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

Which yields: 产生:

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

I know that this is how it's supposed to be, but in my instance Foo is part of my library and Bar is defined by the client, so they won't necessarily be part of the same namespace. 我知道这是应该的,但是在我的实例中, Foo是我的库的一部分,而Bar是由客户端定义的,因此它们不一定是同一名称空间的一部分。 The part where Foo<void>::instance is defined is part of a macro, so I can hide complexity from the user. 定义Foo<void>::instance部分是宏的一部分,因此我可以向用户隐藏复杂性。

Is there any way that enables me to define the member of a class from inside another namespace? 有什么方法可以使我从另一个名称空间内部定义类的成员?

A simple solution for your particular need (assuming that the example code provided is relevant) is to use a Meyers' singleton , eg 一个满足您特定需求的简单解决方案(假设所提供的示例代码相关)是使用Meyers的单例 ,例如

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

Alternatively you can provide a general definition of the static member in the header file, which works fine due to a special exemption for templates in the ODR: 或者,您可以在头文件中提供静态成员的常规定义,由于对ODR中的模板有特殊的豁免,因此可以正常工作:

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

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

Amendment : 修正案

Here's a concrete example of the last method. 这是最后一种方法的具体示例。 It works nicely with g++ 4.8.2 and Visual C++ 12.0 (2013). 它可以与g ++ 4.8.2和Visual C ++ 12.0(2013)很好地配合使用。 I can not remember any problem with it with earlier compiler versions. 我不记得以前的编译器版本有任何问题。

main.cpp main.cpp中
 auto main() -> int {} 
xh XH
#include "x.h"

#include <iostream>

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

#include "x.h"
a.cpp a.cpp
 #include "xh" #include <iostream> struct A {}; static bool u = !(std::cout << "A " << &F::Foo<A>::instance << std::endl); #include "xh" 
a2.cpp a2.cpp
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>_
b.cpp b.cpp
 #include "xh" #include <iostream> struct B {}; static bool u = !(std::cout << "B " << &F::Foo<B>::instance << std::endl); 

Building and running with Visual C++: 使用Visual C ++构建和运行:

\nH:\\dev\\test\\so\\0169> cl main.cpp a.cpp a2.cpp b.cpp /Feb H:\\ dev \\ test \\ so \\ 0169> cl main.cpp a.cpp a2.cpp b.cpp / Feb\nmain.cpp main.cpp中\na.cpp a.cpp\na2.cpp a2.cpp\nb.cpp b.cpp\nGenerating Code... 产生程式码...\n\nH:\\dev\\test\\so\\0169> b H:\\ dev \\ test \\ so \\ 0169> b\nA 00988A50 一个00988A50\nA 00988A50 一个00988A50\nB 00988A6E 00 00988A6E\n\nH:\\dev\\test\\so\\0169>_ H:\\ dev的\\测试\\所以\\ 0169> _\n

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM