如何测试方法是否为const?
How to test if a method is const?
如何获取一个布尔值来指示已知方法是否具有 const 限定符?
例如:
struct A {
void method() const {}
};
struct B {
void method() {}
};
bool testA = method_is_const<A::method>::value; // Should be true
bool testB = method_is_const<B::method>::value; // Should be false
在 type_traits
header 中,我找到了一个可以使用的 is_const
测试,但我需要方法类型,但我不确定如何获得它。
我试过了:std::is_const<decltype(&A::method)>::value
但它不起作用,我能理解为什么 (void (*ptr)() const) != const void (*ptr)()
)。
检查是否可以在 const
限定的左值上调用成员函数要简单得多。
template<class T>
using const_lvalue_callable_foo_t = decltype(std::declval<const T&>().foo());
template<class T>
using has_const_lvalue_callable_foo = std::experimental::is_detected<const_lvalue_callable_foo_t, T>;
冲洗并重复,但 std::declval<const T>()
除外,以检查是否可以在 const
限定的右值上调用所述函数。我想不出 const &&
成员函数的好的用例,因此检测这种情况是否有意义值得怀疑。
参考当前Library Fundamentals 2 TS working draft如何实现is_detected
。
检查特定的成员函数指针类型是否指向具有特定 cv-qualifier-seq 的函数类型要复杂得多。每个 cv-qualifier-seq 需要 6 个部分特化(const
和 const volatile
不同 cv-qualifier-seq s), 仍然不能处理重载的成员函数或成员函数模板。草拟想法:
template<class T>
struct is_pointer_to_const_member_function : std::false_type {};
template<class R, class T, class... Args>
struct is_pointer_to_const_member_function<R (T::*)(Args...) const> : std::true_type {};
template<class R, class T, class... Args>
struct is_pointer_to_const_member_function<R (T::*)(Args...) const &> : std::true_type {};
template<class R, class T, class... Args>
struct is_pointer_to_const_member_function<R (T::*)(Args...) const &&> : std::true_type {};
template<class R, class T, class... Args>
struct is_pointer_to_const_member_function<R (T::*)(Args..., ...) const> : std::true_type {};
template<class R, class T, class... Args>
struct is_pointer_to_const_member_function<R (T::*)(Args..., ...) const &> : std::true_type {};
template<class R, class T, class... Args>
struct is_pointer_to_const_member_function<R (T::*)(Args..., ...) const &&> : std::true_type {};
如果您希望 const volatile
也成为 true
,请按照这些思路取消另外 6 个部分专业化。
std::is_const<decltype(&A::method)>::value
不起作用的原因是 const 成员函数不是 const(成员函数)。它不是 const
的顶级 const int
vs int
.
我们可以做的是使用 void_t
的类型特征来测试我们是否可以在 const T
:
上调用 method
template <typename... >
using void_t = void;
template <typename T, typename = void>
struct is_const_callable_method : std::false_type { };
template <typename T>
struct is_const_callable_method<T, void_t<
decltype(std::declval<const T&>().method())
> > : std::true_type { };
在 C++20 中,事情变得容易多了,因为 concepts 已经标准化,包含了检测习语。
现在我们只需要写这个约束:
template<class T>
concept ConstCallableMethod = requires(const T& _instance) {
{ _instance.method() }
};
ConstCallableMethod
测试表达式 _instance.has_method()
的格式是否正确,因为 _instance
是 const-reference 类型。
鉴于你的两个 classes:
struct A {
void method() const { }
};
struct B {
void method() { }
};
A
(ConstCallableMethod<A>
) 的约束条件为 true
,B
的约束条件为 false
。
如果你想也测试method
函数的return类型是否无效,你可以添加->void
到像这样的约束:
template<class T>
concept ConstCallableMethodReturnsVoid = requires(const T& _instance) {
{ _instance.method() } -> void
};
如果你想更通用一点,你可以传入一个成员函数指针到概念并测试该函数指针是否可以用 const
实例调用(尽管这会少一些当你有过载时很有用):
template<class T, class MemberF>
concept ConstCallableMemberReturnsVoid = requires(const T& _instance, MemberF _member_function) {
{ (_instance.*_member_function)() } -> void
};
你可以这样称呼它:
ConstCallableMemberReturnsVoid<A, decltype(&A::method)>
这允许一些其他理论上的 class,例如 C
,它有一个 const 方法,但它没有命名 method
:
struct C
{
void foobar() const{}
};
我们可以用同样的概念来测试:
ConstCallableMemberReturnsVoid<C, decltype(&C::foobar)>
Live Demo
创建类型特征以确定方法的常量性:
template<typename method_t>
struct is_const_method;
template<typename CClass, typename ReturnType, typename ...ArgType>
struct is_const_method< ReturnType (CClass::*)(ArgType...)>{
static constexpr bool value = false;
};
template<typename CClass, typename ReturnType, typename ...ArgType>
struct is_const_method< ReturnType (CClass::*)(ArgType) const>{
static constexpr bool value = true;
};
如何获取一个布尔值来指示已知方法是否具有 const 限定符?
例如:
struct A {
void method() const {}
};
struct B {
void method() {}
};
bool testA = method_is_const<A::method>::value; // Should be true
bool testB = method_is_const<B::method>::value; // Should be false
在 type_traits
header 中,我找到了一个可以使用的 is_const
测试,但我需要方法类型,但我不确定如何获得它。
我试过了:std::is_const<decltype(&A::method)>::value
但它不起作用,我能理解为什么 (void (*ptr)() const) != const void (*ptr)()
)。
检查是否可以在 const
限定的左值上调用成员函数要简单得多。
template<class T>
using const_lvalue_callable_foo_t = decltype(std::declval<const T&>().foo());
template<class T>
using has_const_lvalue_callable_foo = std::experimental::is_detected<const_lvalue_callable_foo_t, T>;
冲洗并重复,但 std::declval<const T>()
除外,以检查是否可以在 const
限定的右值上调用所述函数。我想不出 const &&
成员函数的好的用例,因此检测这种情况是否有意义值得怀疑。
参考当前Library Fundamentals 2 TS working draft如何实现is_detected
。
检查特定的成员函数指针类型是否指向具有特定 cv-qualifier-seq 的函数类型要复杂得多。每个 cv-qualifier-seq 需要 6 个部分特化(const
和 const volatile
不同 cv-qualifier-seq s), 仍然不能处理重载的成员函数或成员函数模板。草拟想法:
template<class T>
struct is_pointer_to_const_member_function : std::false_type {};
template<class R, class T, class... Args>
struct is_pointer_to_const_member_function<R (T::*)(Args...) const> : std::true_type {};
template<class R, class T, class... Args>
struct is_pointer_to_const_member_function<R (T::*)(Args...) const &> : std::true_type {};
template<class R, class T, class... Args>
struct is_pointer_to_const_member_function<R (T::*)(Args...) const &&> : std::true_type {};
template<class R, class T, class... Args>
struct is_pointer_to_const_member_function<R (T::*)(Args..., ...) const> : std::true_type {};
template<class R, class T, class... Args>
struct is_pointer_to_const_member_function<R (T::*)(Args..., ...) const &> : std::true_type {};
template<class R, class T, class... Args>
struct is_pointer_to_const_member_function<R (T::*)(Args..., ...) const &&> : std::true_type {};
如果您希望 const volatile
也成为 true
,请按照这些思路取消另外 6 个部分专业化。
std::is_const<decltype(&A::method)>::value
不起作用的原因是 const 成员函数不是 const(成员函数)。它不是 const
的顶级 const int
vs int
.
我们可以做的是使用 void_t
的类型特征来测试我们是否可以在 const T
:
method
template <typename... >
using void_t = void;
template <typename T, typename = void>
struct is_const_callable_method : std::false_type { };
template <typename T>
struct is_const_callable_method<T, void_t<
decltype(std::declval<const T&>().method())
> > : std::true_type { };
在 C++20 中,事情变得容易多了,因为 concepts 已经标准化,包含了检测习语。
现在我们只需要写这个约束:
template<class T>
concept ConstCallableMethod = requires(const T& _instance) {
{ _instance.method() }
};
ConstCallableMethod
测试表达式 _instance.has_method()
的格式是否正确,因为 _instance
是 const-reference 类型。
鉴于你的两个 classes:
struct A {
void method() const { }
};
struct B {
void method() { }
};
A
(ConstCallableMethod<A>
) 的约束条件为 true
,B
的约束条件为 false
。
如果你想也测试method
函数的return类型是否无效,你可以添加->void
到像这样的约束:
template<class T>
concept ConstCallableMethodReturnsVoid = requires(const T& _instance) {
{ _instance.method() } -> void
};
如果你想更通用一点,你可以传入一个成员函数指针到概念并测试该函数指针是否可以用 const
实例调用(尽管这会少一些当你有过载时很有用):
template<class T, class MemberF>
concept ConstCallableMemberReturnsVoid = requires(const T& _instance, MemberF _member_function) {
{ (_instance.*_member_function)() } -> void
};
你可以这样称呼它:
ConstCallableMemberReturnsVoid<A, decltype(&A::method)>
这允许一些其他理论上的 class,例如 C
,它有一个 const 方法,但它没有命名 method
:
struct C
{
void foobar() const{}
};
我们可以用同样的概念来测试:
ConstCallableMemberReturnsVoid<C, decltype(&C::foobar)>
Live Demo
创建类型特征以确定方法的常量性:
template<typename method_t>
struct is_const_method;
template<typename CClass, typename ReturnType, typename ...ArgType>
struct is_const_method< ReturnType (CClass::*)(ArgType...)>{
static constexpr bool value = false;
};
template<typename CClass, typename ReturnType, typename ...ArgType>
struct is_const_method< ReturnType (CClass::*)(ArgType) const>{
static constexpr bool value = true;
};