美文网首页
C++ 20:Concepts

C++ 20:Concepts

作者: fck_13 | 来源:发表于2020-05-13 15:55 被阅读0次

我们从一个例子来引入concepts:

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>

int main()
{
    std::vector<int> container{1, 5, 4, 3, 2};

    std::ostream_iterator<int> out(std::cout, " ");
    std::copy(std::begin(container), std::end(container), out);
    std::cout<<"\n";

    std::sort(std::begin(container), std::end(container));
    
    std::copy(std::begin(container), std::end(container), out);
    std::cout<<"\n";

    return 0;
}

运行结果如下:


image.png

程序正确,得到了我们想要的结果。

现在我们修改一下容器的类型,改为std::list。然后编译就出错了,而且错误信息很多,根本就没有办法知道错误到底是啥,需要在哪里修改。

image.png

然后你会一点一点的分析,最后找到了答案了:
迭代器分为五个类别(在C++20之前是5个,C++20增加了contiguous_iterator_tag ):

struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag : input_iterator_tag {};
struct bidirectional_iterator_tag : forward_iterator_tag {};
struct random_access_iterator_tag : bidirectional_iterator_tag {};

std::sort中的迭代器参数需要的是random_access_iterator_tagstd::vector的迭代器类型为random_access_iterator_tag,而std::list的迭代器类型为bidirectional_iterator_tag,所以编译错误。
当我们找到问题的答案后,才发现这个问题的原因是如此的简单,但是编译器给出的错误信息确是如此的复杂且不知所以然。

这里的问题在于,对于std::sort的参数是有限制的,不是说任何的迭代器都是可用的。为了明确编程中的一些限制,C++给出了concepts。

我们继续我们上面的例子,修改如下:

#include <concepts>
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <list>

template<typename T>
concept sortable = requires(T t, size_t i){t[i];};

template<sortable T>
void sort(T& t){
    std::sort(std::begin(t), std::end(t));
}

int main()
{
    std::vector<int> container{1, 5, 4, 3, 2};

    std::ostream_iterator<int> out(std::cout, " ");
    std::copy(std::begin(container), std::end(container), out);
    std::cout<<"\n";

    sort(container);

    std::copy(std::begin(container), std::end(container), out);
    std::cout<<"\n";

    return 0;
}

这里我们增加了

template<typename T>
concept sortable = requires(T t, size_t i){t[i];};

意思是新增加了一种concept,也就是一种限制,将一个类型现定于有operator[]成员函数。这里我们假设有这个成员函数的类型满足random_access_iterator_tag迭代器。
然后我们声明了一个sort函数:

template<sortable T>
void sort(T& t){
    std::sort(std::begin(t), std::end(t));
}

告知调用者其参数类型应当满足sortable这个限制。

然后我们将std::vector<int> container{1, 5, 4, 3, 2};改为std::list<int> container{1, 5, 4, 3, 2};,重新编译代码,得到下面的错误

image.png
这样看起来是不是容易理解多了。

相关文章

网友评论

      本文标题:C++ 20:Concepts

      本文链接:https://www.haomeiwen.com/subject/slvnnhtx.html