包含指向成员的指针的内联成员初始值设定项
Inline member initializer containing pointer to member
在工作中,我正在进行一些实验,以便在我们的代码库中引入一些反射。基本上,我想要实现的是在数据成员的初始值设定项的类型中捕获一个指向数据成员的指针:
template<class Class, int Class::*dataMember>
struct Reflect
{
operator int() {return 0;}
};
class Foo
{
public:
int bar = Reflect<Foo, &Foo::bar>{};
};
尽管clang 3.4.1(http://gcc.godbolt.org/)和英特尔C++XE 14.0能够编译这段代码,当使用MSVC12时,我收到以下错误消息:
错误C2065:"bar":未声明的标识符
错误C2975:"dataMember":"Reflect"的模板参数无效,应为编译时常量表达式
此外,gcc 4.9.2似乎也有问题:http://ideone.com/ZUVOMO.
所以我的问题是:
- 上面的代码是有效的C++11吗
- 如果是,对于失败的编译器,是否有任何解决方法
VC++抱怨的当然不是问题;【basic.scope.pdecl】/1,6:
名称的声明点紧接在其完成之后声明符(第8条)及其初始值设定项之前(如果有),除非如下所述。[…]
在类成员的声明点之后,成员名称可以在其类的范围内查找
这意味着名称查找是可以的。然而,正如@hvd在评论中指出的那样,这种结构的语法存在一定的歧义
大概GCC会解析上面的行,直到逗号:
int bar = Reflect<Foo,
// at this point Reflect < Foo can be a perfectly fine relational-expression.
// stuff after the comma could be a declarator for a second member.
一旦遇到其他人就会跳伞。
一个让GCC满意的变通方法是
int bar = decltype( Reflect<Foo, &Foo::bar>{} )();
演示。不过,这对VC++没有帮助,它显然混淆了错误消息所指示的声明点。因此,将初始值设定项移动到构造函数中是可行的:
int bar;
Foo() : bar( Reflect<Foo, &Foo::bar>{} ) {}
// (also works for GCC)
而在bar
的声明处提供初始值设定项则不能rextester上的演示#2。
相关文章:
- 从成员指针到整个结构/类的强制转换
- OOP 中的单成员指针
- 使用结构成员指针在C++中填充结构
- 聚合初始化,将成员指针设置为同一结构成员
- 空指针常量 (nullptr)、空指针值和空成员指针值之间有什么区别?
- 共享 C++ 的数据成员指针
- 如何声明指向成员内容的成员指针m_pmd/m_pmf并访问它们?
- 从类C++外部调用指向成员方法的成员指针
- 结构成员指针是否自动初始化为零?
- 如何删除类内类类型的类成员指针
- 是否打印指向已定义 int 的成员指针
- 指向常量的成员指针
- 通过此指针访问时的成员差异和自身的成员指针(简单的 QT 示例问题)
- 类数据成员指针的非类型模板参数包无法使用 gcc 编译
- 为什么我不能在同一行中定义两个相同类型的类的成员指针
- 将类成员指针传递给 Lambda 捕获列表 c++11
- 在单一实例类中将成员指针设置为 null 的正确方法是什么
- 无法删除在destructor中的成员指针的课程
- 删除对象而不调用成员指针的析构函数
- 当派生类的基类具有成员指针时,对其进行深层复制