C++ 何时重载逗号运算符?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5602112/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 18:29:21  来源:igfitidea点击:

When to Overload the Comma Operator?

c++functionoperator-overloading

提问by user541686

I see questions on SO every so often about overloading the comma operator in C++ (mainly unrelated to the overloading itself, but things like the notion of sequence points), and it makes me wonder:

我经常看到关于在 C++ 中重载逗号运算符的问题(主要与重载本身无关,但与序列点的概念有关),这让我想知道:

When shouldyou overload the comma? What are some examples of its practical uses?

什么时候应该重载逗号?它的实际用途有哪些例子?

I just can't think of any examples off the top of my head where I've seen or needed to something like

我只是想不出任何我见过或需要的例子

foo, bar;

in real-world code, so I'm curious as to when (if ever) this is actually used.

在现实世界的代码中,所以我很好奇什么时候(如果有的话)实际使用它。

采纳答案by ildjarn

Let's change the emphasis a bit to:

让我们稍微改变一下重点:

When should youoverload the comma?

当要重载逗号?

The answer: Never.

答案是:从来没有。

The exception: If you're doing template metaprogramming, operator,has a special place at the very bottom of the operator precedence list, which can come in handy for constructing SFINAE-guards, etc.

例外:如果你在做模板元编程,operator,在运算符优先级列表的最底部有一个特殊的地方,它可以派上用场,用于构建 SFINAE-guards 等。

The only two practical uses I've seen of overloading operator,are both in Boost:

我见过的重载的唯一两个实际用途operator,都在Boost 中

回答by Petter

I have used the comma operator in order to index maps with multiple indices.

我使用逗号运算符来索引具有多个索引的地图。

enum Place {new_york, washington, ...};

pair<Place, Place> operator , (Place p1, Place p2)
{
    return make_pair(p1, p2);
}


map< pair<Place, Place>, double> distance;

distance[new_york, washington] = 100;

回答by GManNickG

Boost.Assignuses it, to let you do things like:

Boost.Assign使用它,让你做这样的事情:

vector<int> v; 
v += 1,2,3,4,5,6,7,8,9;

And I've seen it used for quirky language hacks, I'll see if I can find some.

我已经看到它用于古怪的语言技巧,我会看看是否能找到一些。



Aha, I do remember one of those quirky uses: collecting multiple expressions. (Warning, dark magic.)

啊哈,我确实记得那些古怪的用法之一:收集多个表达式。(警告,黑魔法。)

回答by Alexandre C.

The comma has an interesting property in that it can take a parameter of type void. If it is the case, then the built-in comma operator is used.

逗号有一个有趣的特性,它可以接受一个类型为 的参数void。如果是这种情况,则使用内置的逗号运算符。

This is handy when you want to determine if an expression has type void:

当您想确定表达式是否具有类型 void 时,这很方便:

namespace detail_
{
    template <typename T>
    struct tag
    {
        static T get();
    };

    template <typename T, typename U>
    tag<char(&)[2]> operator,(T, tag<U>);

    template <typename T, typename U>
    tag<U> operator,(tag<T>, tag<U>);
}

#define HAS_VOID_TYPE(expr) \
    (sizeof((::detail_::tag<int>(), \
             (expr), \
             ::detail_::tag<char>).get()) == 1)

I let the reader figure out as an exercise what is going on. Remember that operator,associates to the right.

作为练习,我让读者弄清楚发生了什么。请记住,operator,右侧的关联。

回答by Josh Kelley

Similar to @GMan'sBoost.Assignexample, Blitz++overloads the comma operator to provide a convenient syntaxfor working with multidimensional arrays. For example:

@GMan 的Boost.Assign示例类似,Blitz++重载了逗号运算符以提供用于处理多维数组的便捷语法。例如:

Array<double,2> y(4,4);   // A 4x4 array of double
y = 1, 0, 0, 0,
    0, 1, 0, 0,
    0, 0, 1, 0,
    0, 0, 0, 1;

回答by moooeeeep

In SOCI - The C++ Database Access Libraryit is used for the implementation of the inbound part of the interface:

SOCI - C++ 数据库访问库中,它用于实现接口的入站部分:

sql << "select name, salary from persons where id = " << id,
       into(name), into(salary);

From the rationale FAQ:

基本原理常见问题解答

Q: Overloaded comma operator is just obfuscation, I don't like it.

Well, consider the following:

"Send the query X to the server Y and put result into variable Z."

Above, the "and" plays a role of the comma. Even if overloading the comma operator is not a very popular practice in C++, some libraries do this, achieving terse and easy to learn syntax. We are pretty sure that in SOCI the comma operator was overloaded with a good effect.

问:重载的逗号运算符只是一种混淆,我不喜欢它。

那么,请考虑以下几点:

“将查询 X 发送到服务器 Y 并将结果放入变量 Z。”

上面的“and”起到了逗号的作用。即使重载逗号运算符在 C++ 中不是一个非常流行的做法,一些库也会这样做,实现简洁易学的语法。我们非常确定在 SOCI 中,逗号运算符过载并产生了良好的效果。

回答by CygnusX1

I use the comma operator for printing log output. It actually is very similar to ostream::operator<<but I find the comma operator actually betterfor the task.

我使用逗号运算符来打印日志输出。它实际上非常类似于ostream::operator<<但我发现逗号运算符实际上适合该任务。

So I have:

所以我有:

template <typename T>
MyLogType::operator,(const T& data) { /* do the same thing as with ostream::operator<<*/ }

It has these nice properties

它有这些不错的特性

  • The comma operator has the lowest priority. So if you want to stream an expression, things do not mess up if you forget the parenthesis. Compare:

    myLog << "The mask result is: " << x&y; //operator precedence would mess this one up
    myLog, "The result is: ", x&y;
    

    you can even mix comparisons operators inside without a problem, e.g.

    myLog, "a==b: ", a==b;
    
  • The comma operator is visually small. It does not mess up with reading when gluing many things together

    myLog, "Coords=", g, ':', s, ':', p;
    
  • It aligns with the meaningof the comma operator, i.e. "print this" and then "print that".

  • 逗号运算符的优先级最低。所以如果你想流式传输一个表达式,如果你忘记了括号,事情就不会搞砸了。相比:

    myLog << "The mask result is: " << x&y; //operator precedence would mess this one up
    myLog, "The result is: ", x&y;
    

    您甚至可以在内部混合比较运算符而不会出现问题,例如

    myLog, "a==b: ", a==b;
    
  • 逗号运算符在视觉上很小。将许多东西粘在一起时,不会影响阅读

    myLog, "Coords=", g, ':', s, ':', p;
    
  • 它与逗号运算符的含义一致,即“打印这个”然后“打印那个”。

回答by Jerry Coffin

One possibility is the Boost Assignlibrary (though I'm pretty sure some people would consider this abuse rather than a good use).

一种可能性是Boost Assign库(尽管我很确定有些人会认为这种滥用而不是很好的用途)。

Boost Spiritprobably overloads the comma operator as well (it overloads almost everything else...)

Boost Spirit可能也会重载逗号运算符(它几乎重载了其他所有内容......)

回答by AC.

Along the same lines, I was sent a github pull request with comma operator overload. It looked something like following

同样,我收到了一个带有逗号运算符重载的 github 拉取请求。它看起来像以下

class Mylogger {
    public:
            template <typename T>
            Mylogger & operator,(const T & val) {
                    std::cout << val;
                    return * this;
            }
 };

 #define  Log(level,args...)  \
    do { Mylogger logv; logv,level, ":", ##args; } while (0)

then in my code I can do:

然后在我的代码中我可以这样做:

 Log(2, "INFO: setting variable \", 1, "\"\n");

Can someone explain why this is a good or bad usage case?

有人可以解释为什么这是一个好的或坏的用例吗?

回答by iammilind

One of the practical usage is for effectively using it with variable arguments in macro. By the way, variable arguments was earlier an extension in GCC and now a part of C++11 standard.

实际用法之一是有效地将它与宏中的变量参数一起使用。顺便说一下,可变参数早先是 GCC 的扩展,现在是 C++11 标准的一部分。

Suppose we have a class X, which adds object of type Ainto it. i.e.

假设我们有一个class X,它将类型的对象添加A到其中。IE

class X {
  public: X& operator+= (const A&);
};

What if we want to add 1 or more objects of Ainto X buffer;?
For example,

如果我们想要1个或多个对象添加AX buffer;
例如,

#define ADD(buffer, ...) buffer += __VA_ARGS__

Above macro, if used as:

上面的宏,如果用作:

ADD(buffer, objA1, objA2, objA3);

then it will expand to:

然后它将扩展为:

buffer += objA1, objeA2, objA3;

Hence, this will be a perfect example of using comma operator, as the variable arguments expand with the same.

因此,这将是使用逗号运算符的完美示例,因为变量参数扩展相同。

So to resolve this we overload commaoperator and wrap it around +=as below

所以为了解决这个问题,我们重载comma运算符并将其包装+=如下

  X& X::operator, (const A& a) {  // declared inside `class X`
    *this += a;  // calls `operator+=`
  }