3

我想出了利用decltype在.cpp文件中定义静态成员,然后使用这个宏的想法:使用decltype定义静态成员(智能感知不同意)

#define DEFINE_SYMBOL(x) decltype(x) x 

这种方式,例如如果类Foo声明static int bar,我可以做Foo.cpp中的以下内容:

DEFINE_SYMBOL(Foo::bar) = 1337; 

这似乎有点“哈克”,但它有具有弹性在原始符号类型变化的优势。例如,如果bar更改为foo.hpp中的未签名,则不需要更改foo.cpp。当成员类型复杂时,阅读也更容易。

但是,如果静态成员是私有的,则在Visual Studio 2015中,Intellisense会抱怨使用decltype(称为无法访问)。抱怨很有道理,虽然程序编译得很好。现在,我的问题是,Intellisense是错误的,还是不推荐使用decltype(以及为什么)?

+1

gcc和clang接受它([Demo](http://coliru.stacked-crooked.com/a/c1bde595c6627cc7)),Msvc接受它。我认为这是一个intellisense错误。 – Jarod42

+0

看起来像IntelliSense认为'DEFINE_SYMBOL(Foo :: bar)'是一个函数调用而不是宏。 –

回答

1

智能感知是不正确,GCC和铿锵编译一个类似的计划,我们可以看到C++草案标准节11[class.access]说:

在第11章的所有访问控制影响的能力从特定实体的声明中访问类成员名称,包括宣布的实体名称前的声明部分,并且如果实体是类,则该类成员的定义出现在类的成员之外 - 规范。 [注意:此访问也适用于对构造函数,转换函数和析构函数的隐式引用。 末端注] [实施例:

class A { 
typedef int I; // private member 
I f(); 
friend I g(I); 
static I x; 
template<int> struct Q; 
template<int> friend struct R; 
protected: 
struct B { }; 
}; 
A::I A::f() { return 0; } 
A::I g(A::I p = A::x); 
A::I g(A::I p) { return 0; } 
A::I A::x = 0; 
template<A::I> struct A::Q { }; 
template<A::I> struct R { }; 
struct D: A::B, A { }; 

在这里,所有的使用A ::我都能很好地形成,因为A :: F,A :: x和A :: Q为A类的成员并且g和 R是类A的朋友。例如,这意味着首次使用A :: I的访问检查必须推迟到 ,直到确定A :: I的这种使用是返回类型类似地, 使用A :: B作为基指定符是格式良好的,因为D是从A派生的,所以必须延迟基指定符 的检查,直到整个基指定符为止。名单已被看到。 - 示例]