Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The void(), the comma operator (operator,) and the impossible (?) overloading

Tags:

Consider the following struct:

struct S {};

In C++14, the definition below is valid:

constexpr auto f() { return S{}, 'c'; }

As well as the following one:

constexpr auto f() { return S{}, void(); }

Now, consider the following, working snippet that involves the first of the two definitions:

#include<type_traits>

struct S {};

constexpr int operator,(S, char) { return 42; }
constexpr auto f() { return S{}, 'c'; }

int main() {
    constexpr int i{f()};
    static_assert(i == 42, "!");
    static_assert(std::is_same<decltype(f()), int>::value, "!");
}

Speaking not so technically, the overload of the comma operator intercepts the couple S{}, 'c' and returns an integer, as correctly verified in the main function.

Now, suppose I want to do the same with the second definition of f:

constexpr auto f() { return S{}, void(); }

In this case, the comma operator should intercept the form S{}, void().
Neither the following definition works (for obvious reasons):

constexpr int operator,(S, void) { return 42; }

Nor the one below (that would have worked in the previous case):

template<typename T> constexpr int operator,(S, T &&) { return 42; }

Is there any way to overload the comma operator so as to deal with S{}, void()?
Isn't it otherwise a lack in the standard, for it allows to use the comma operator that way, but doesn't give you the chance to overload the same operator (even if the standard mentions that overloaded functions involving S are allowed)?


Note: this question is made for the sake of curiosity. Please, avoid comments like do not do that or it is not good practice. I'm not planning to do that in production environments. Thank you.

like image 601
skypjack Avatar asked Sep 15 '16 15:09

skypjack


People also ask

Can comma operator be overloaded?

In C++, we can overload the comma operator using Operator Overloading. For Example: For “Send the query X to the server Y and put the result in variable Z”, the “and” plays the role of the comma.

What is comma operator overloading in C++?

The purpose of comma operator is to string together several expressions. The value of a comma-separated list of expressions is the value of the right-most expression. Essentially, the comma's effect is to cause a sequence of operations to be performed. The values of the other expressions will be discarded.

What does comma operator do?

The comma operator ( , ) evaluates each of its operands (from left to right) and returns the value of the last operand. This lets you create a compound expression in which multiple expressions are evaluated, with the compound expression's final value being the value of the rightmost of its member expressions.

Can [] be overloaded in C ++?

An overloaded operator (except for the function call operator) cannot have default arguments or an ellipsis in the argument list. You must declare the overloaded = , [] , () , and -> operators as nonstatic member functions to ensure that they receive lvalues as their first operands.


1 Answers

The relevant clause for this is 13.3.1.2/9 [over.match.oper] in N4140:

If the operator is the operator ,, the unary operator &, or the operator ->, and there are no viable functions, then the operator is assumed to be the built-in operator and interpreted according to Clause 5.

As void() is never a valid function argument (see 5.2.2/7 [expr.call]), there never is a viable function and thus the built-in , will be used.

So no, what you are trying to do is not possible.

In fact, writing an iterator loop like this

for(...; ++it1, (void)++it2)

is a standard way to prevent users from breaking your code by overloading , for their iterator types by enforcing the built-in operator , to be used. (Note that I am not saying you need to do this in your everyday code. It very much depends on its actual use. This is standard library level of paranoid.)


Regarding the standard clause you linked:

The meaning of the operators =, (unary) &, and , (comma), predefined for each type, can be changed for specific class and enumeration types by defining operator functions that implement these operators.

But such a function cannot be defined because, as I said above, void() is never a valid function argument.

Now whether or not this is an oversight/problem in the standard is open to debate.

like image 100
Baum mit Augen Avatar answered Sep 25 '22 21:09

Baum mit Augen