Search code examples
c++volatilemethod-chainingoperator-precedence

Chained calls of member functions - order of calls


I have a large application containing chained function calls, like this:

subsystem.
    do_stuff(cfg().get("x")).
    do_stuff(cfg().get("y"));

Here subsystem is an object of a class type:

struct Sybsystem
{
    Sybsystem& do_stuff(int parameter)
    {
        ... // much code
        return *this; // this line makes it possible to chain calls
    }
};

Also, cfg() is a "global function" that returns a configuration object:

struct Configuration
{
    int get(const char* param_name);
}
Configuration& cfg();

The code with the chained function calls first does stuff with x, then with y; however, C++ doesn't define when the configuration parameters for x and y are extracted from the configuration object. Indeed, when i run my application in Debug and Release mode (MS Visual Studio 2005), the order of calls to Configuration::get is opposite.

All was well until we added support for returning random values from Configuration::get (for testing). When we did it, the behavior in Debug and Release mode became different.

So my question is:

Can i fix this problem and still use chained function calls? (we have much code written this way; it would be tiresome to change it all)

Can i use, for example, tricks with volatile?


Solution

  • No, you can't. The order of evaluation of function arguments is unspecified, and there's nothing you can do about it.

    You'll have to break the chain to create your own sequence points where this order is important.