c++custom-operator

How do I make a custom operator evaluate left-to-right?


I want to evaluate a()|b() left-to-right, but I get a different order depending on whether I use the built-in operator or a custom operator.

    class Foo {
        public: Foo operator| (Foo f) {
            return Foo();
        }
    };
    std::string out;
    auto f1 = [&out](std::string s) { out += s; return false; };
    auto f2 = [&out](std::string s) { out += s; return Foo(); };
    f1("a") | f1("b");
    f2("c") | f2("d");
    std::cout << out;

The output is abdc. How do I make the custom operator evaluate left-to-right?


Solution

  • You cannot. At least not with an overloaded operator|. The evaluation order of operands to functions and most operators in unspecified in C++.

    For the built-in ||, operator order is left-to-right, but you cannot overload that operator to return anything but bool because it would cease to be "built-in ||". If you give your Foo class an operator bool() const which converts to bool, then you can write f2("x") || f2("y") but the right expression will not be evaluated if the left evaluates to true, and it will very likely emit a branch instruction in the compiler's output.

    You could overload operator, (or use the built-in) as well, which then would be sequenced in the way you are looking for.

    More details:

    1. Every value computation and side effect of the first (left) argument of the built-in logical AND operator &&, the built-in logical OR operator || and the built-in comma operator , is sequenced before every value computation and side effect of the second (right) argument.
    2. Every value computation and side effect associated with the first expression in the conditional operator ?: is sequenced before every value computation and side effect associated with the second or third expression.