【问题标题】:Is it bad style to overload operators on std containers in global scope?在全局范围内重载标准容器上的运算符是不好的风格吗?
【发布时间】:2014-06-02 23:53:30
【问题描述】:

我遇到了这个问题:

// 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
    }
 }

问题(如here 所述)是a += b; 无法编译,因为Bar::operator+=(Qux&amp;, Qux const &amp;) 隐藏了::operator+=;而 ADL 没有找到 ::operator+,因为在这种情况下 ADL 只搜索 namespace std;

这很棘手,因为只有在包含 B.h 时才会出现问题——但 B.h 显然与 Buffer 无关。代码不应该根据我是否包含另一个标题而中断。

(其实我是在换编译器的时候才发现的,之前我用的编译器确实名字查找不正确,接受了代码)。

我的问题是:A.h 中的过载是否因为这个问题而成为一个坏主意?

我现在通过在namespace Bar 中使用B.h 来解决这个问题,但这似乎很老套,有更好的选择吗?

【问题讨论】:

  • 如果在代码中添加using ::operator+=; 会怎样?
  • 我认为Kerrek 的意思是如果你将using ::operator+=; 添加到foo 会发生什么?
  • 你的意思是把它添加到每个使用它的函数中?似乎比在B.h 中做一次更 hacker :)
  • 如果您要为std 命名空间中定义的任何类型重载任何运算符,我建议在std 命名空间中执行此操作。这与 ADL 配合得很好。
  • @RSahu 很遗憾,它是添加到 std 的 UB(参见 [namespace.std]#1

标签: c++ operator-overloading argument-dependent-lookup


【解决方案1】:

我能想到的最简单、最安全、最可重用的方法是让+= 参数之一是运算符命名空间中的一种类型:

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 以供更广泛使用,而不是使用代码中动态分配的实例也被设计为拥有和处理基类。

【讨论】:

    【解决方案2】:

    虽然我不确定在这种情况下运算符重载是否风格不好, (如您所知,这可能是一个有争议的问题), 这似乎是“功能范围”的问题,而不是“操作员”的问题。 即使你把 'operator+=()' 改成 'Add()', 你可能会得到相同的结果。

    在这种情况下,运算符重载是否是不良风格与问题无关。

    【讨论】:

    • 确实如此;所以我也可以通过调用我的函数“my_buffer_append”来解决这个问题,这比operator+=更不可能发生冲突。
    猜你喜欢
    • 1970-01-01
    • 2017-09-12
    • 1970-01-01
    • 2020-10-19
    • 1970-01-01
    • 1970-01-01
    • 2010-10-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多