需要某种运算符.. c ++

时间:2010-09-02 11:07:36

标签: c++

我想在队列中存储一串字符串。如果我使用成员函数push()

,这似乎很简单
queue test;
string s0("s0"), s1("s1");

test.push(s0);
test.push(s1);

我正在考虑以隐式方式在队列中添加字符串。这意味着,如果我键入以下字符串序列,例如operator >>应该在队列中推送字符串值。

queue test;
string s0("s0"), s1("s1");

s0 >> s1 >> s2 >> s3 ;

有没有办法做到这一点?

6 个答案:

答案 0 :(得分:16)

虽然C ++不允许这样做,但它允许你做一些非常相似的事情:test << s0 << s1;然而, 不这样做!

如果我看到test.push(s0),我确切地知道它的作用,甚至没有看test的类型。如果我看到test << s0 << s1;,我认为test是一个写入的流。


这是我的在重载运算符时应该遵循的三个基本规则

  1. 尽管看似明显的相反证据,但只有极少数情况下运营商超载是合适的。因此,重载运算符的第一个也是最重要的规则是:不要这样做。这可能看起来很奇怪,但原因是实际上很难理解背后的语义除非在应用领域中使用运营商是众所周知且无可争议的,否则应用运营商。与普遍认为相反,情况并非如此。 每当操作符的含义不明显且无可争议时,就不应该重载。 而是提供一个具有良好选择名称的函数。
  2. C ++对重载运算符的语义几乎没有限制。您的编译器将很乐意接受实现二进制+运算符的代码来更改其右操作数。但是,此类运算符的用户永远不会怀疑表达式a + b来更改b的值。这就是为什么运算符重载的第二条规则说: 始终坚持运算符的众所周知的语义。 (反过来,这假定语义是无可争议的;请参阅以前的规则。)
  3. 最后,请始终记住,运营商彼此之间以及与其他运营相关。如果您的类型支持a + b,则用户也可以拨打a += b。如果它支持前缀增量++ a,那么他们也希望++能够工作。如果他们可以检查是否a < b,他们肯定也希望能够检查是否a > b。如果他们可以复制构造您的类型,他们希望分配也可以工作。因此,运营商重载的第三条规则会提醒您: 始终提供一系列相关操作。

  4. 与所有这些规则一样,确实有例外。有时人们偏离了它们,结果并不是错误的代码,但这种偏差很少而且很远。至少,我所看到的100个这样的偏差中有99个是没有道理的。然而,它可能只有1000中的999。所以你最好坚持这些规则。

    所以,以防我不够清楚:对于你问题的代码,偏离这些规则是非常糟糕的。

答案 1 :(得分:3)

首先,你的'隐式'排队项目的例子没有提到队列 - 你的意思是:

test << s0 << s1 << s2 << s3;

如果是这样,它可能是 ,但我不推荐它。它真的无法提供可读性。但是,如果你真的想要它,可以将它放在某个地方的标题中,并将它包含在你想要这种行为的任何地方:

template<typename T>
std::queue<T> &operator<<(std::queue<T> &q, const T &v)
{
    q.push(v);
    return q;
}

请注意,由于C ++优先级规则,相反的顺序 - s0 >> s1 >> s2 >> test - 不可能

答案 2 :(得分:3)

我不会真的这样做,但如果你真的觉得需要提供这种语法,你可以编写一个插件适配器......

template <typename C>
class inserter_type {
public:
   typedef C container_type;
   typedef typename container_type::value_type value_type;

   explicit inserter_type( container_type & container ) : container(container) {}
   inserter_type& operator<<( value_type const & value ) {
      container.push( value );
      return *this;
   }
private:
   container_type & container;
};
template <typename C>
inserter_type<C> inserter( C & container ) {
   return inserter_type<C>(container);
}
int main() {
   std::queue<std::string> q;
   inserter(q) << "Hi" << "there";
}

答案 3 :(得分:2)

Qt容器的工作原理如下:

QStringList list;
list << "Sven" << "Kim" << "Ola";

QVector<QString> vect = list.toVector();
// vect: ["Sven", "Kim", "Ola"]

如果您希望使用相同的STL容器,则需要自己编写运算符重载,但显然您无法向std命名空间添加操作。

答案 4 :(得分:0)

如果您想这样做,通常会表示为

test << s0 << s1 << s2 << s3;

通过在队列类上重载operator<<的合适定义。我不知道为什么这会比一系列简单的test.push()电话更好。

答案 5 :(得分:0)

我同意大多数答案,这些答案告诉你,只要你包括队列对象,你就可以做到,而且我也同意可读性受到损害,因为它是非常非标准行为

不过,我很想知道。如果您尝试以下内容怎么办?

queue test;
string s0("s0"), s1("s1");

test.push(s0).push(s1);

这可以非常简单地实现,仍然会给你正确的可读性(因为push的含义很好理解),并保持你的代码简洁(这似乎是你的主要目标)。

要实现它,您所要做的就是扩展Queue类(或者编写自己的队列类,然后再绕过STL Queue对象)。