有没有办法针对不同的数据类型优化 operator+=

Is there a way to optimize the operator+= for different data types

“我不是专业人士,我只是在学习!”

我想在我的 class 中支持添加运算符,例如 Buffer。

class Buffer : public vector<uint8_t>
{
public:
    Buffer() = default;

    Buffer& operator += (const char* str)
    {
        auto pStr = str;
        while(*pStr)
        {
            emplace_back(*pStr);
            ++pStr;
        }
        return *this;
    }

    template<typename T>
    Buffer& operator += (const initializer_list<T>& ByteArray)
    {
        this->operator+=<vector<T>>(ByteArray);
        return *this;
    }
    template<class OtherContainer>
    Buffer& operator += (const OtherContainer& ByteArray)
    {
        std::copy(ByteArray.begin(), ByteArray.end(), std::back_inserter(*this));
        return *this;
    }

    template<typename T, size_t size>
    Buffer& operator += (const T (& arr)[ size ] )
    {
        std::copy( std::begin( arr ),  std::end( arr ), std::back_inserter(*this));
        return *this;
    }
};

我想覆盖:

int main()
{
    vector<uint8_t> vec = {48,49,50,51};
    string str = "45";
    char arr[] = {60,61,62,63};
    Buffer b;
    b += vec;
    b += str;
    b += "67";
    b += {56,57,58,59};
    b += arr;

    return 0;
}

是否可以编写一个适用于所有情况的漂亮模板?或者至少组合成一个“initializer_list”、“vector”、“string”?也许在某个地方您可以避免“复制”并使用“移动”?

如果您使用 C++20,那么您可以使用 requires 尽可能地减少这些函数。

class Buffer 
    : public std::vector<uint8_t>
{
public:
    Buffer() = default;

    template<typename T>
    Buffer& operator+=(const T& any)
        // Any container that has iterators or arrays.
        requires requires { std::begin(any); std::end(any); }
    {
        std::copy(std::begin(any), std::end(any), std::back_inserter(*this));
        return *this;
    }

    // This is a must if you want to allow:
    // b += {1, 2, 3};
    // And to not force the user to specify it's an initializer list:
    // b += std::initializer_list{1, 2, 3};
    template<typename T> 
    Buffer& operator+=(const std::initializer_list<T>& list)
    {
        std::copy(list.begin(), list.end(), std::back_inserter(*this));
        return *this;
    }
};

此外,第一个重载将接受 任何 具有迭代器的容器。

请注意,我没有检查容器中的类型,所以如果您执行以下操作:

struct S{};
std::vector<S> vec;
b += vec;

这会导致令人不快的错误。

要移动数据,您只需将 std::copy 替换为:

std::move(std::begin(any), std::end(any), std::back_inserter(*this));