c++ - 包含指向成员的指针的内联成员初始值设定项

标签 c++ templates c++11 initializer 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/ ) 和 Intel C++ XE 14.0 能够编译这段代码,但在使用 MSVC12 时,我收到以下错误消息:

error C2065: 'bar' : undeclared identifier

error C2975: 'dataMember' : invalid template argument for 'Reflect', expected compile-time constant expression

此外,gcc 4.9.2 似乎也有问题:http://ideone.com/ZUVOMO .

所以我的问题是:

  1. 上述代码是否适用于 C++11?
  2. 如果是,是否有任何解决失败编译器的方法?

最佳答案

VC++ 提示的当然不是问题; [basic.scope.pdecl]/1,6:

The point of declaration for a name is immediately after its complete declarator (Clause 8) and before its initializer (if any), except as noted below.[…]

After the point of declaration of a class member, the member name can be looked up in the scope of its class.

这意味着名称查找没问题。但是,正如@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 的声明中提供初始值设定项时不能。 Demo #2在 rextester 上。

关于c++ - 包含指向成员的指针的内联成员初始值设定项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29392234/

相关文章:

c++ - 如何使用 VS Debugger 找出模板参数的类型?

perl - 模板::工具包变量处理

c++ - 使用STL对部分 vector 进行排序

C++ 自定义时间日期结构到 utc 纪元

c++ - 为什么 "while (*sea++ = *river++);"没有正常工作?

c++ - 如何在C++中创建指针数组

c++ - 使用模板链接错误

c++ - 在范围适配器的迭代器类中实现 operator->

c++ - 用于嵌入式开发的 Linux 发行版?

c++ - OpenGL 重绘相同参数的不同渲染结果