有没有办法检测自身内部的 类 常量?
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
本身,结果总是 false
。 References [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)>>;
你可能会
constexpr bool isConst() const {
return std::is_const_v<std::remove_pointer_t<decltype(this)>>;
}
你的问题是 decltype(this)
是 /*const*/ X&
(不是 /*const*/ X
)
另一个问题是您需要 2 个版本(一个用于非常量对象):
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>>;
}
这是不可能的。即使在非 const 限定的对象上也可以毫无问题地调用 const 限定的方法。检查 decltype(this)
类型根本没有帮助,因为它不考虑调用此方法的对象的类型,只考虑隐式 this
参数的类型。
考虑以下示例并输出:
#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
本身,结果总是 false
。 References [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)>>;
你可能会
constexpr bool isConst() const {
return std::is_const_v<std::remove_pointer_t<decltype(this)>>;
}
你的问题是 decltype(this)
是 /*const*/ X&
(不是 /*const*/ X
)
另一个问题是您需要 2 个版本(一个用于非常量对象):
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>>;
}
这是不可能的。即使在非 const 限定的对象上也可以毫无问题地调用 const 限定的方法。检查 decltype(this)
类型根本没有帮助,因为它不考虑调用此方法的对象的类型,只考虑隐式 this
参数的类型。