有没有办法检测自身内部的 类 常量?

Is there a way to detect a classes constness inside of itself?

考虑以下示例并输出:

#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,this 的常量始终取决于编译时上下文,而不是在运行时确定或隐式模板化。

是否有其他方法可以从内部检测 class 的常量性?如果是这样,这将简化与迭代器相关的代码等。

我知道要使其工作,所有 const 函数都必须为 const/非 const 实例化隐式模板化。所以这可能是不可能的。

编辑: 原始示例错误地使用 std::is_const_v<decltype(*this)> 并始终返回 false.

*this returns 引用(对 const 或非 const),因此 std::is_const_v<decltype(*this)> 正在检查引用的常量性;但引用不能是 const 本身,结果总是 falseReferences [dcl.ref]/1

Cv-qualified references are ill-formed except when the cv-qualifiers are introduced through the use of a typedef-name ([dcl.typedef], [temp.param]) or decltype-specifier ([dcl.type.simple]), in which case the cv-qualifiers are ignored.

我想你想检查对象(被引用)的常量性;您可以将 std::remove_reference 添加为

return std::is_const_v<std::remove_reference_t<decltype(*this)>>;

LIVE

你可能会

constexpr bool isConst() const {
    return std::is_const_v<std::remove_pointer_t<decltype(this)>>;
} 

Demo

你的问题是 decltype(this)/*const*/ X&(不是 /*const*/ X

另一个问题是您需要 2 个版本(一个用于非常量对象):

constexpr bool isConst() {
    return std::is_const_v<std::remove_pointer_t<decltype(this)>>;
} 

Demo

proposal p0847r0

这将允许:

template <typename Self>
constexpr bool is_const_with_proposal(Self&& this self)
{
    return std::is_const_v<std::remove_reference_t<Self>>;
}

这是不可能的。即使在非 const 限定的对象上也可以毫无问题地调用 const 限定的方法。检查 decltype(this) 类型根本没有帮助,因为它不考虑调用此方法的对象的类型,只考虑隐式 this 参数的类型。