首页 > 解决方案 > 将模板参数约束为仅接受带有 C++20 概念的 std::vector 和 std::list

问题描述

我正在尝试编写一个仅对 std::vector 或 std::list 中的数字进行排序的程序,我为此做了两个概念:

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
}

我脑海中出现的问题是,当我通过 a 时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;
}

标签: c++templatesc++20sfinaec++-concepts

解决方案


这:

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它既是 avector又是 a 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>.


这与为什么这是你的约束的问题是分开的 - 为什么你只能排序vectorand list... 而不能 like dequeor stringor spanor ... ?或者为什么你只限于intfloat

您可以对任何可排序的前向范围进行冒泡排序。我会表达为:

template <std::ranges::forward_range R>
    requires std::totally_ordered<std::ranges::range_reference_t<R>>
void BubbleSort(R& r);

推荐阅读