在全局范围内重载std容器上的操作符是不好的风格吗?
Is it bad style to overload operators on std containers in global scope?
我遇到了这样的问题:
// A.h
#include <vector>
typedef std::vector<unsigned char> Buffer;
Buffer &operator+=(Buffer &a, Buffer const &b);
// B.h
namespace Bar
{
struct Qux { };
Qux &operator+=(Qux &a, Qux const &b);
}
// Foo.cpp
#include "A.h"
#include "B.h" // comment this out, error goes away
namespace Bar
{
void foo()
{
Buffer a, b;
a += b; // error
}
}
问题(如这里所述)是a += b;
无法编译,因为Bar::operator+=(Qux&, Qux const &)
隐藏了::operator+=
;并且ADL没有找到::operator+
,因为在这种情况下ADL只搜索namespace std;
。
这是棘手的,因为问题只出现在B.h
,但B.h
显然与Buffer
无关。代码不应该中断取决于我是否包含另一个头。
(实际上我只是在更换编译器时才发现这个问题,我之前使用的编译器名称查找错误,并接受了代码)。
我的问题是:在A.h
过载只是一个坏主意,因为这个问题?
我现在通过B.h
在namespace Bar
内做using ::operator+=;
来解决这个问题,但这似乎很hacky,有更好的选择吗?
我能想到的最简单、最安全、最可重用的方法是让+=
参数中的一个属于操作符命名空间中的类型:
template <typename T>
struct ArgumentRef
{
ArgumentRef(T& t) : t_(t) { }
operator T&() { return t_; }
operator const T&() const { return t_; }
T& t_;
};
typedef std::vector<unsigned char> Buffer;
Buffer &operator+=(ArgumentRef<Buffer> a, Buffer const &b) { }
也就是说,继承——由于vector
中的非虚拟析构函数而在c++圈子中引起争议——在我看来通常是好的,特别是如果您没有在API中公开Buffer
以供更广泛的使用,并且没有在设计为拥有和处理基类的代码中使用动态分配的实例。
虽然我不确定在这种情况下操作符重载是否具有不良风格,(你知道,这可能是一个有争议的问题),这似乎是一个"功能范围"的问题,而不是一个"操作符"的问题。即使您将'operator+=()'更改为'Add()',你可能会得到相同的结果。
在这种情况下,操作符重载是否具有糟糕的样式与这个问题无关。
相关文章:
- Qt VTK交互风格的信号到小部件
- 我可以使用条件运算符初始化C风格的字符串文字吗
- Visual Studio 2019:插入多个C++风格的单行注释
- 如何在本地机器上运行c++和javascript客户端代码(hackerbank风格)
- 重载运算符<<采用谷歌 C++ 风格
- C++许多 SFINAE 风格的过载
- 谷歌风格指南(前向分枝部分)
- 如何使用 cmake pack redhat 风格的 rpm,这是主要的和"-devel"?
- 如何用符合C++核心准则的代码替换C风格的字符串解析
- 如何编写一个类似于kernellist_head的c++风格的双链表实现
- 用现代C++STL数据结构替换旧的C风格数组
- 为什么map有操作符[],set没有
- 如何确保 C/C++ 代码中不会缺少 doxygen 风格的文档注释?
- C++(Visual Studio)有Java风格的注释吗?
- 如何"Re-Polish"相同风格的QApplication?
- 如何按照 Google C++风格指南连接字符串文字?
- 如何为特定的构建风格设置 cpp 文件夹
- 使用 rangesv3 在 c++ 中模拟 python 风格的列表理解?
- c++中的C风格字符串和操作符重载
- 在全局范围内重载std容器上的操作符是不好的风格吗?