C ++ 11 decltype
返回给定的表达式的类型(主要是)。但这可能与表达式的类型不同,因为它实际上是可访问的:
template<typename T>
struct Ref {
Ref(T&) { }
};
#define GETTYPE decltype
//#define GETTYPE typeof
struct Problem {
void doit_c() const { Ref<GETTYPE(n)> rn{n}; }
void doit_nc() { Ref<GETTYPE(n)> rn{n}; }
int n;
};
int main() {
int i;
const int ci = 0;
Problem pr;
// decltype == typeof == int
Ref<GETTYPE(i)> ri{i};
pr.doit_nc();
// decltype == typeof == const int
Ref<GETTYPE(ci)> rci{ci};
Ref<GETTYPE(static_cast<const int&>(i))> rcci{static_cast<const int&>(i)};
// typeof == const int, decltype == int (!)
pr.doit_c();
return 0;
}
在该示例中,Ref
结构仅用于在T
与实际构造函数参数不匹配时导致编译错误。 Problem::doit_c()
方法是decltype(n)
返回非const结果的地方,即使n
在此上下文中是常量。
如果从标准decltype
切换到GNU扩展typeof
,这似乎考虑了方法的常量。
现在我的问题:是否存在符合C ++ 11 / C ++ 14 / C ++ 17的替代decltype()
/ typeof()
的行为&#34;正确&#34;对于像上面const方法中的声明这样的表达式,如上所述:上面没有编译错误?
编辑:
简化了第一句话,删除了一些错误并停止分散注意力问题(谢谢,@ skypjack)
在示例代码中简化了宏的使用(谢谢@Richard Critten)
答案 0 :(得分:6)
decltype
是一种有时同时坐在两把椅子上的功能。首先,顾名思义,它可以为您提供实体的确切声明类型,忽略使用它的上下文。其次,它可以将其论证视为一个表达式,其确切类型取决于上下文及其值类别。
decltype
直接应用于“裸”(未加括号)的类成员访问是一种特殊情况,decltype
根据其第一个角色执行操作。它不会将n
视为表达式。相反,它将生成该类成员的类型,忽略上下文。
如果您希望将n
视为表达式,则必须将其括起来
struct Problem {
void doit_c() const
{
Ref<decltype(n)> rn1{n}; // `decltype(n)` is `int` -> ERROR
Ref<decltype((n))> rn2{n}; // `decltype((n))` is `const int &` -> compiles OK
}
};
答案 1 :(得分:1)
您可以使用临时引用找出n
的有效cv限定类型:
void doit_c() const { auto& x = n; Ref<GETTYPE(x)> rn{n}; }
void doit_nc() { auto& x = n; Ref<GETTYPE(x)> rn{n}; }
但是,如AnT's answer所示,括号内容更简单明了。