const Binding Wrapper::s_Bindi-6ren">
gpt4 book ai didi

c++ - 在某个随机命名空间中专门化和定义模板静态成员是否可以?

转载 作者:太空狗 更新时间:2023-10-29 21:46:43 26 4
gpt4 key购买 nike

我有这样的代码:

template<> const string &Wrapper<Foo>::s_Name = "Foo";
template<> const Binding Wrapper<Foo>::s_Bindings[] = {
Binding("m1", &caller<&Foo::f1>),
Binding("m2", &caller<&Foo::f2>),
Binding("m3", &caller<&Foo::f1>),
Binding("outer", &caller<&outer>),
};
template<> const int Wrapper<Foo>::s_BindingsLength =
(sizeof(ArraySizeHelper(s_Bindings)));

这里的 ArraySizeHelper 在编译时计算数组大小。可以绑定(bind)非成员函数和成员函数。我写了一些宏来节省编写这些绑定(bind)的时间:

#define BIND_START(Class) \
namespace _Bind##Class##Namespace { \
typedef Class _BindClass; \
template<> const string &Wrapper<_BindClass>::s_Name = #Class; \
template<> const Binding Wrapper<_BindClass>::s_Bindings[] = {

#define BIND(FunctionName, Function) \
Binding(FunctionName, &caller<Function>),

#define BIND_END \
};\
template<> const int Wrapper<_BindClass>::s_BindingsLength = \
(sizeof(ArraySizeHelper(s_Bindings))); \
}

现在上面的代码可以这样写:

BIND_START(Foo)
BIND("m1", &Foo::f1)
BIND("m2", &Foo::f2)
BIND("m3", &Foo::f1)
BIND("outer", &outer)
BIND_END

输入和阅读更容易。为什么我需要把它放在命名空间中?因为我找不到另一种方法来编写这些宏,使得类名必须只写一次(成员函数指针除外)并将其与多个类一起使用。现在我想知道,这样做可以吗?如果没有,是否有任何其他方法来实现我想要的功能?

Full code of this example on Pastebin


这似乎是 GCC 4.7.2 中的错误(其他版本不确定)

此代码违反了 9.4.2/2:“静态数据成员的定义应出现在包含成员类定义的命名空间范围内。”
这是错误报告:GCC Bugzilla – Bug 56119

最佳答案

您的解决方案似乎被 C++11 标准禁止。这是 9.4.2/2 所说的:

“静态数据成员在其类定义中的声明不是定义,可能是除 cv 限定的 void 之外的不完整类型。静态数据成员的定义应出现在包含成员类定义的命名空间范围"

现在,您定义静态成员数据(其名称是评估 _Bind##Class##Namespace 预处理器表达式的结果)的命名空间包含定义类的命名空间(即,在你的情况,全局命名空间)。因此,静态数据成员定义是非法的。

我不确定您使用的是什么编译器,但如果它编译了那个,那么它就是一个错误(例如,确实这似乎是 GCC 4.7.2 的情况)。 Clang 3.2 正确拒绝对其进行编译并生成正确的输出消息:

source.cpp:106:1: error: cannot define or redeclare 's_Name' here because namespace '_BindFooNamespace' does not enclose namespace 'Wrapper<Foo>'
BIND_START(Foo)

至于替代方案,我认为没有,只要你在BIND_END的扩展中需要类名即可。 (这是编译时初始化 s_BindingsLength 所需要的)。如果宏没有将类名作为参数,事实上,该名称必须作为 typedef 可用。 (如果允许宏扩展为 #define 指令,这将是正确的,但事实并非如此)。自 BIND_END没有关于如何形成类名的提示,它必须寻找一个始终相同的名称。如果名称必须始终相同,则必须将其放入单独的命名空间以避免名称冲突。但这被上述标准的规则所禁止。

换句话说,恐怕你必须添加一个参数BIND_END宏。毕竟这还算不错。

关于c++ - 在某个随机命名空间中专门化和定义模板静态成员是否可以?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14537188/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com