C++20 中的概念

时间:2021-01-13 10:39:38

标签: c++ c++20

我最近开始用 C++ 编程。我正在尝试学习用 c++20 表示的概念。当我在做我的作业时,我遇到了一个问题。有人能告诉为什么这不想编译吗?

它报告:

1.Error C3864 'ns1::BufferedCollection<T>': requires clause is incompatible with the declaration for each function  

BufferedCollectionHeader.h

namespace ns1
{
    template<typename T>
    concept AddableComparable= requires (const T& a,const T& b)
    {
        {a + b} -> std::convertible_to<T>;
        {a < b} -> std::convertible_to<bool>;
    };

    template<typename T>
    concept Printable = requires(std::ostream stream,const T& a)
    {
        {stream << a} -> std::convertible_to<decltype(stream)>;
    };

    template<typename T>
    concept AddableComparablePrintable = AddableComparable<T> && Printable<T>;

    template<typename T>
    requires AddableComparablePrintable<T>
    class BufferedCollection : public IPrintable
    {
        static_assert(std::is_copy_assignable<T>::value, "Tip T nije copy_assignable");
        static_assert(std::is_move_assignable<T>::value, "Tip T nije move_assignable");
        int elements;
        int buffers;
        int capacity;

        template<typename K>
        struct Node
        {
            int capacity;
            K* p;
            Node<K>* next;
        };

        Node<T>* list;
    public:
        BufferedCollection(int)noexcept;
        ...
    };
}

BufferedCollection.h

#include "BufferedCollectionHeader"
template<typename T>
requires ns1::AddableComparablePrintable<T>
ns1::BufferedCollection<T>::BufferedCollection(int n)noexcept: elements(0),buffers(0),capacity(n),list(nullptr){};
...

源.cpp

class TestClass:public ns1::IPrintable
{
    int x;
public:
    friend std::ostream& operator<<(std::ostream& stream, const TestClass& test)
    {
        stream << test.to_string();
        return stream;
    }
    TestClass(int n):x(n){}
    std::string to_string()const noexcept override
    {
        return std::to_string(x);
    }
    TestClass operator+(const TestClass& t)const
    {
        return TestClass(t.x + x);
    }
    bool operator<(const TestClass& t)const
    {
        return true;
    }
};
int main()
{
    ns1::BufferedCollection<TestClass>  bc(3);
    return 0;
}

注意事项:

  • IPrintable 是代表可打印对象的抽象类。
  • 我在两个文件中分发了 BufferedCollection 类的代码,因为它在分配中是必需的

2 个答案:

答案 0 :(得分:0)

您不应该按价值获取数据流。它们不可复制。

friend std::ostream& operator<<(std::ostream& stream, const TestClass& test)

您需要 const 限定您的 +<,因为约束看起来是 const T &

TestClass operator+(const TestClass& t) const;
bool operator<(const TestClass& t) const;

旁白:你为什么要为only +<<< 定义一个概念? std::three_way_comparable 有什么问题?

为什么是 static_assert 可分配性,而不是概念?

答案 1 :(得分:0)

concept Printable = requires(std::ostream stream,const T& a) 应该得到一个引用作为输入(在朋友定义中也是如此!):

    template<typename T>
    concept Printable = requires(std::ostream &stream,const T& a)
                                              ^~~~~~~                                              
    {
        {stream << a} -> std::convertible_to<decltype(stream)>;
    };

除此之外,您的 TestClass 的加法和比较运算符应标记为 const。如果你改变它,它编译正常:live demo。我进一步简化了您的示例并将其放入单个文件中。因此,我不确定这是否能解决您的所有问题。

更新

从这个 comparison 可以看出,GCC 和 clang 编译但 MSVC 仍然拒绝代码。