我想到了使用decltype
在.cpp文件中定义静态成员,然后使用这个宏的想法:
#define DEFINE_SYMBOL(x) decltype(x) x
这样,例如,如果类Foo
声明static int bar
,我可以在foo.cpp中执行以下操作:
DEFINE_SYMBOL(Foo::bar) = 1337;
这似乎有点“hacky”,但它具有对原始符号类型的变化具有弹性的优点。例如,如果bar在foo.hpp中更改为unsigned,我就不需要更改foo.cpp。当成员的类型很复杂时,它也更容易阅读。
但是,如果静态成员是私有的,在Visual Studio 2015中,Intellisense会抱怨使用decltype(说它不可访问)。投诉很有意义,虽然程序编译得很好。现在,我的问题是,Intellisense是错误的,还是不建议使用decltype(以及为什么)?
答案 0 :(得分:1)
Intellisense不正确,gcc和clang都编译了一个类似的程序,我们可以看到草案C ++标准部分11
[class.access] 说:
第11条中的所有访问控制都会影响从特定实体的声明访问类成员名称的能力,包括声明的实体名称前面的声明部分,如果 entity是一个类,类的成员定义出现在类的成员规范之外。 [注意:此访问权限也适用于对构造函数,转换函数和析构函数的隐式引用。 - 尾注] [例子:
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 :: I的所有用法都是格式正确的,因为A :: f,A :: x和A :: Q是A类和g类的成员, R是A类的朋友。这意味着,例如,首次使用A :: I时的访问检查必须是 延迟直到确定A :: I的这种使用作为A类成员的返回类型。同样, 使用A :: B作为基本说明符是格式良好的,因为D是从A派生的,因此检查基本说明符 必须延迟,直到看到整个base-specifier-list。 - 例子]