0

我有一个看起来像这样的类:

class A {
  public:
    A() {};
    A& operator<< (A& a, unsigned int i);

  private:
    vector<int> abc;
}

我想提供abc使用运算符添加对象的能力:

A a();
a << 3,4,5; // should do the same as several calls of abc.push_back(i)

我知道我必须重载<<运算符,我是否也必须重载,运算符?

实际的方法会是什么样子?

4

3 回答 3

9

永远,永远,,在 C++ 中重载运算符。该语言允许这样做,但您不能这样做并保留操作员的预期行为。(特别是,逗号运算符是 C++ 中的一个序列点:编译器保证左侧表达式将在右侧表达式之前计算。如果重载它,则不再保证将计算哪个表达式第一的。)

您想使用流插入运算符的多次调用来插入多个对象。

(为了完整起见:你永远不应该重载的其他 C++ 运算符是&&and ||。同样,不可能提供客户端代码所期望的行为(在这种情况下是短路))。

于 2013-06-02T15:50:46.180 回答
7

如果您想保留您的方面,a << 1, 2, 3可以将您的重载更改operator<<为接受initializer_listof int,而不是单个int

#include <initializer_list>

class A {
    public:
    A() {};
    A& operator<< (std::initializer_list<int> values);

    private:
    vector<int> abc;
}

然后像这样实现它:

A& A::operator<< (std::initializer_list<int> values)
{
    for(const auto& value : values)
        abc.push_back(value);
    return *this;
}

只需按如下方式使用它:

A a;
a << {1, 2, 3, 4};

你唯一需要确保的是你有一个兼容 C++11 的编译器来提供这些特性。

于 2013-06-02T15:59:52.313 回答
1

Eigen 库实现了这种语法。不确定那是不是你来自的地方。

Eigen 是一个表达式模板库。它定义了看似做事的运算符和函数,但它们只是代理对象的工厂。代理形成编译时,有时是运行时数据结构,它们决定何时以及如何进行计算。

要实现这种语法,您需要代理对象。将其类似于std::ostream. a << 3返回一个代理“流”对象,然后重载operator ,以启用该, 4, 5部分。代理也可以重载operator<<,在这种情况下,语法为a << 3 << 4 << 5. 这可以说是更干净,但是 Eigen 是一个数学和运算符重载密集型库,并且,作为最低优先级运算符具有特殊的地位,这减少了在诸如a << 3, true? 4 : 42, 5.

长话短说,operator<<即使你这样做,你也应该坚持下去。

class A {
  public:
    A() {};

    inserter operator << (A& a, unsigned int i) {
      inserter ret( * this );
      ret , i;
      return ret;
    }

  private:
    vector<int> abc;

    struct inserter {
      A &client;

      inserter( A &in_client ) : client( in_client ) {}

      inserter &operator , ( int x ) {
        client.abc.push_back( x );
        return this;
      }
    };
    friend struct inserter;
};
于 2013-06-02T16:15:55.297 回答