有没有一种方法可以检测到一个类本身内部的constness?

问题描述 投票:0回答:1

请看下面的例子和输出。

#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 函数必须隐含在模板中,以用于 constconst 实例。所以这可能是不可能的。

EDIT:原来的例子错误地使用了 std::is_const_v<decltype(*this)> 并总是返回 false.

c++ c++17 const constexpr
1个回答
1
投票

你可以这样做

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)>>;
} 

演示版

提案P0847R0

这将允许。

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

3
投票

*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)>>;

生活


2
投票

即使在非const-qualified对象上,const-qualified方法也可以毫无问题地被调用。检查 decltype(this) 类型没有任何帮助,因为它没有考虑这个方法被调用的对象的类型,只考虑了隐式的 this 争论。

© www.soinside.com 2019 - 2024. All rights reserved.