有没有办法针对不同的数据类型优化 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));
“我不是专业人士,我只是在学习!”
我想在我的 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));