使用 C++ 20 概念检查函数 returns 是否为 const 值
Using c++ 20 Concept to check if a function returns a const value
我正在尝试使用概念来检测给定类型的开始函数 returns 是“const T&”还是“T&”的迭代器。但我不确定最好的做法是什么,我尝试了以下方法:
#include <iostream>
#include <concepts>
#include <vector>
#include <set>
template <typename T>
concept IsConst = std::is_const<T>::value;
template<typename T>
concept IsIterableOfConst = requires (T& t) { { *t.begin() } -> IsConst; };
template <IsIterableOfConst T>
void test()
{
std::cout << "Yes" << std::endl;
}
template <typename T>
void test()
{
std::cout << "No" << std::endl;
}
int main(int argc, char** argv)
{
test<std::set<int>>();
test<std::vector<int>>();
}
这会产生输出“No No”,而我希望它产生输出“Yes No”,因为据我所知,std::set 中的迭代器应该始终迭代“const”集合持有类型的版本。如何正确检测到容器包含常量值?
这里的直接问题是 decltype((*t.begin()))
for std::set<int>
给你类型 int const&
,类型特征 std::is_const<T>
检查 T
是否是一些输入 U const
。引用不是常量。
您需要先删除引用:
template <typename T>
concept IsConst = std::is_const_v<std::remove_reference_t<T>>;
也就是说,这并不是一个完全正确的常量检查。考虑 views::iota(0, 10)
范围,它根据需要为您提供一堆整数。这个范围的引用类型是int
(不是int&
,不是int const&
,只是int
)。这是 not const
类型,所以你的概念会说这样的范围不建模 IsIterableOfConst
(旁注:术语是范围,不可迭代).但是这样的范围确实是 const - 你不能修改它的内容。
所以更接近的答案是:
template <typename T>
inline constexpr bool is_suitably_const = true;
template <typename T>
inline constexpr bool is_suitably_const<T&> = is_const_v<T>;
template <typename R>
concept RangeOfConst = range<R> && is_suitably_const<range_reference_t<R>>;
这表示 vector<int>
不是 RangeOfConst
,set<int>
和 vector<int> const
是 iota_view<int>
。
但是...它还会说 vector<bool>
是 RangeOfConst
,即使您 可以 修改它们!我会把那个留给以后思考。
直接的方法是,如果T
是const,那么T
应该和add_const_t<T>
是同一类型,所以你只需要改变你的IsConst
至
template <typename T>
concept IsConst = std::is_same_v<T, std::add_const_t<T>>;
我正在尝试使用概念来检测给定类型的开始函数 returns 是“const T&”还是“T&”的迭代器。但我不确定最好的做法是什么,我尝试了以下方法:
#include <iostream>
#include <concepts>
#include <vector>
#include <set>
template <typename T>
concept IsConst = std::is_const<T>::value;
template<typename T>
concept IsIterableOfConst = requires (T& t) { { *t.begin() } -> IsConst; };
template <IsIterableOfConst T>
void test()
{
std::cout << "Yes" << std::endl;
}
template <typename T>
void test()
{
std::cout << "No" << std::endl;
}
int main(int argc, char** argv)
{
test<std::set<int>>();
test<std::vector<int>>();
}
这会产生输出“No No”,而我希望它产生输出“Yes No”,因为据我所知,std::set 中的迭代器应该始终迭代“const”集合持有类型的版本。如何正确检测到容器包含常量值?
这里的直接问题是 decltype((*t.begin()))
for std::set<int>
给你类型 int const&
,类型特征 std::is_const<T>
检查 T
是否是一些输入 U const
。引用不是常量。
您需要先删除引用:
template <typename T>
concept IsConst = std::is_const_v<std::remove_reference_t<T>>;
也就是说,这并不是一个完全正确的常量检查。考虑 views::iota(0, 10)
范围,它根据需要为您提供一堆整数。这个范围的引用类型是int
(不是int&
,不是int const&
,只是int
)。这是 not const
类型,所以你的概念会说这样的范围不建模 IsIterableOfConst
(旁注:术语是范围,不可迭代).但是这样的范围确实是 const - 你不能修改它的内容。
所以更接近的答案是:
template <typename T>
inline constexpr bool is_suitably_const = true;
template <typename T>
inline constexpr bool is_suitably_const<T&> = is_const_v<T>;
template <typename R>
concept RangeOfConst = range<R> && is_suitably_const<range_reference_t<R>>;
这表示 vector<int>
不是 RangeOfConst
,set<int>
和 vector<int> const
是 iota_view<int>
。
但是...它还会说 vector<bool>
是 RangeOfConst
,即使您 可以 修改它们!我会把那个留给以后思考。
直接的方法是,如果T
是const,那么T
应该和add_const_t<T>
是同一类型,所以你只需要改变你的IsConst
至
template <typename T>
concept IsConst = std::is_same_v<T, std::add_const_t<T>>;