请看下面的例子和输出。
#include <type_traits>
#include <iostream>
struct X {
bool is_const = std::is_const_v<std::remove_pointer_t<decltype(this)>>;
constexpr bool isConst1() const {
return is_const;
}
constexpr bool isConst2() const {
return std::is_const_v<std::remove_pointer_t<decltype(this)>>;
}
};
int main() {
X a;
const X b;
std::cout << "X is const (1): " << a.isConst1() << '\n';
std::cout << "X is const (2): " << a.isConst2() << '\n';
std::cout << "const X is const (1): " << b.isConst1() << '\n';
std::cout << "const X is const (2): " << b.isConst2() << '\n';
return 0;
}
X is const (1): 0
X is const (2): 1
const X is const (1): 0
const X is const (2): 1
很明显,不管一个类型是否真的是const,这个类型的constness this
总是取决于编译时的上下文,而不是在运行时确定或隐式模板。
是否有其他方法可以从类的内部检测到类的constness?如果有的话,这将简化与迭代器相关的代码等。
我知道,要做到这一点,所有的 const
函数必须隐含在模板中,以用于 const
非const
实例。所以这可能是不可能的。
EDIT:原来的例子错误地使用了 std::is_const_v<decltype(*this)>
并总是返回 false
.
你可以这样做
constexpr bool isConst() const {
return std::is_const_v<std::remove_pointer_t<decltype(this)>>;
}
你的问题是 decltype(this)
是 /*const*/ X&
(不是 /*const*/ X
)
另一个问题是,你需要2个版本(非const对象的版本)。
constexpr bool isConst() {
return std::is_const_v<std::remove_pointer_t<decltype(this)>>;
}
这将允许。
template <typename Self>
constexpr bool is_const_with_proposal(Self&& this self)
{
return std::is_const_v<std::remove_reference_t<Self>>;
}
*this
返回一个引用(到 const
或非const
),所以 std::is_const_v<decltype(*this)>
正在检查引用的const-ness;但引用不能是 const
而结果总是 false
. 参考文献[dcl.ref]1
Cv-qualified 引用是错误的,除非 cv-限定符是通过使用 typedef-name ([dcl.typedef], [temp.param]) 或 decltype-specifier ([dcl.type.simple]) 引入的,在这种情况下,cv-限定符会被忽略。
我想你想检查对象(被引用)的const-ness;你可以添加 std::remove_reference
作为
return std::is_const_v<std::remove_reference_t<decltype(*this)>>;
即使在非const-qualified对象上,const-qualified方法也可以毫无问题地被调用。检查 decltype(this)
类型没有任何帮助,因为它没有考虑这个方法被调用的对象的类型,只考虑了隐式的 this
争论。