在工作中,我正在做一些实验,以便在代码库中引入一些反思。基本上,我想要实现的是在数据成员的初始化器类型中捕获指向数据成员的指针:
template<class Class, int Class::*dataMember>
struct Reflect
{
operator int() {return 0;}
};
class Foo
{
public:
int bar = Reflect<Foo, &Foo::bar>{};
};虽然clang3.4.1 (http://gcc.godbolt.org/)和Intel C++ XE14.0能够编译这段代码,但当使用MSVC12时,我得到以下错误消息:
错误C2065:“bar”:未声明的标识符 错误C2975:'dataMember‘:“反射”的无效模板参数,预期编译时常量表达式
此外,gcc 4.9.2似乎也有问题:http://ideone.com/ZUVOMO。
所以我的问题是::
发布于 2015-04-01 14:02:33
VC++抱怨的当然不是问题;basic.cope. about /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>{} )();Demo。但是,这对VC++没有帮助,因为它显然混淆了错误消息所指示的声明点。因此,将初始化程序移动到构造函数中将有效:
int bar;
Foo() : bar( Reflect<Foo, &Foo::bar>{} ) {}
// (also works for GCC)..。虽然在声明bar时提供了初始化程序,但不能。rextester上的Demo #2。
https://stackoverflow.com/questions/29392234
复制相似问题