使用 C++20 概念限制模板参数仅接受 std::vector 和 std::list
Constraint a template parameter to only accept std::vector and std::list with C++20 concepts
我正在尝试编写一个仅对 std::vector 或 std::list 中的数字进行排序的程序
为此我做了 2 个概念:
template<typename T>
concept ValidContainer = requires(T a) {
std::same_as<T, std::vector<typename T::value_type>>;
std::same_as<T, std::list<typename T::value_type>>;
};
并且:
template<typename T>
concept Sortable = requires(T a) {
ValidContainer<T> && std::same_as<typename T::value_type, int>;
ValidContainer<T> && std::same_as<typename T::value_type, float>;
};
以及对它们进行排序的函数的签名:
void BubbleSort(Sortable auto& collection)
{
// sort algorithm
}
我脑海中浮现的问题是,当我传递 std::vector<std::string>
时,它没有向我显示编译错误?
int main()
{
std::vector<int> test = { 32, 3, 6, 8, 2, 5, 0, 43, 67, 1 };
std::vector<std::string> test2 = { "first", "second", "third" };
BubbleSort(test); // this is ok
BubbleSort(test2); // shouldn't this be a compile error?
return 0;
}
requires
表达式是 true
如果封闭的表达式 格式正确 。表达式本身的计算结果是否为 true
.
并不重要
(事实上,requires-expression 中的表达式 never 计算)
您似乎没有解决测试表达式是否格式正确的问题。您的概念应如下所示:
template<typename T>
concept ValidContainer =
std::same_as<T, std::vector<typename T::value_type>> ||
std::same_as<T, std::list<typename T::value_type>>;
template<typename T>
concept Sortable =
( ValidContainer<T> && std::same_as<typename T::value_type, int> ) ||
( ValidContainer<T> && std::same_as<typename T::value_type, float> );
这个:
template<typename T>
concept ValidContainer = requires(T a) {
std::same_as<T, std::vector<typename T::value_type>>;
std::same_as<T, std::list<typename T::value_type>>;
};
正在检查 表达式 std::same_as<T, std::vector<typename T::value_type>>;
是否有效,而不是它也是 true
。也就是说,它基本上只是检查 typename T::value_type
是一个东西。
在那种形式下,如果你想要求一些东西,你必须使用requires
:
template<typename T>
concept ValidContainer = requires(T a) {
requires std::same_as<T, std::vector<typename T::value_type>>;
requires std::same_as<T, std::list<typename T::value_type>>;
};
尽管现在我们要求 T
既是 vector
又是 list
,所以这永远不会成立。所以我们真的需要:
template <typename T>
concept ValidContainer =
std::same_as<T, std::vector<typename T::value_type>>
|| std::same_as<T, std::list<typename T::value_type>>;
尽管这也不是很好,因为现在我们正在拒绝 std::vector<T, MyAlloc>
。
这与为什么这是你的约束的问题是分开的 - 为什么你只能对 vector
和 list
进行排序......但不能像 deque
或 string
或 span
或...?或者为什么您只限于 int
和 float
?
您可以对任何可排序的正向范围进行冒泡排序。我会表达为:
template <std::ranges::forward_range R>
requires std::totally_ordered<std::ranges::range_reference_t<R>>
void BubbleSort(R& r);
我正在尝试编写一个仅对 std::vector 或 std::list 中的数字进行排序的程序 为此我做了 2 个概念:
template<typename T>
concept ValidContainer = requires(T a) {
std::same_as<T, std::vector<typename T::value_type>>;
std::same_as<T, std::list<typename T::value_type>>;
};
并且:
template<typename T>
concept Sortable = requires(T a) {
ValidContainer<T> && std::same_as<typename T::value_type, int>;
ValidContainer<T> && std::same_as<typename T::value_type, float>;
};
以及对它们进行排序的函数的签名:
void BubbleSort(Sortable auto& collection)
{
// sort algorithm
}
我脑海中浮现的问题是,当我传递 std::vector<std::string>
时,它没有向我显示编译错误?
int main()
{
std::vector<int> test = { 32, 3, 6, 8, 2, 5, 0, 43, 67, 1 };
std::vector<std::string> test2 = { "first", "second", "third" };
BubbleSort(test); // this is ok
BubbleSort(test2); // shouldn't this be a compile error?
return 0;
}
requires
表达式是 true
如果封闭的表达式 格式正确 。表达式本身的计算结果是否为 true
.
(事实上,requires-expression 中的表达式 never 计算)
您似乎没有解决测试表达式是否格式正确的问题。您的概念应如下所示:
template<typename T>
concept ValidContainer =
std::same_as<T, std::vector<typename T::value_type>> ||
std::same_as<T, std::list<typename T::value_type>>;
template<typename T>
concept Sortable =
( ValidContainer<T> && std::same_as<typename T::value_type, int> ) ||
( ValidContainer<T> && std::same_as<typename T::value_type, float> );
这个:
template<typename T>
concept ValidContainer = requires(T a) {
std::same_as<T, std::vector<typename T::value_type>>;
std::same_as<T, std::list<typename T::value_type>>;
};
正在检查 表达式 std::same_as<T, std::vector<typename T::value_type>>;
是否有效,而不是它也是 true
。也就是说,它基本上只是检查 typename T::value_type
是一个东西。
在那种形式下,如果你想要求一些东西,你必须使用requires
:
template<typename T>
concept ValidContainer = requires(T a) {
requires std::same_as<T, std::vector<typename T::value_type>>;
requires std::same_as<T, std::list<typename T::value_type>>;
};
尽管现在我们要求 T
既是 vector
又是 list
,所以这永远不会成立。所以我们真的需要:
template <typename T>
concept ValidContainer =
std::same_as<T, std::vector<typename T::value_type>>
|| std::same_as<T, std::list<typename T::value_type>>;
尽管这也不是很好,因为现在我们正在拒绝 std::vector<T, MyAlloc>
。
这与为什么这是你的约束的问题是分开的 - 为什么你只能对 vector
和 list
进行排序......但不能像 deque
或 string
或 span
或...?或者为什么您只限于 int
和 float
?
您可以对任何可排序的正向范围进行冒泡排序。我会表达为:
template <std::ranges::forward_range R>
requires std::totally_ordered<std::ranges::range_reference_t<R>>
void BubbleSort(R& r);