-1

I want to create a class only for setting params for function. I'm using a fluent interface for that. Some function returns the object to setting params and real code will execute in the destructor of this object.

First of all, is it a good idea? Is this a common way to improve code readability when I have a lot of parameters? Or maybe I should use another way to do that? I would be glad to advise on this.

If it's okay, how can I prevent accidentally saving an object to a local variable? In this case, the destructor will be called at end of the variable scope.

Example:

class MyClass {
public:
    ~MyClass() noexcept {
        // some code to execute immediately after setting params A and B
    }

    // abstract setting methods
    MyClass &SetA() { return *this; }
    MyClass &SetB() { return *this; }
};

MyClass SomeFunction() {
    return MyClass();
}

int main() {
    // Correct usage:
    SomeFunction()
            .SetA()
            .SetB();
    // destructor here

    // I want to prevent it:
    auto my_class = SomeFunction();
    my_class
            .SetA()
            .SetB();

    {
        auto my_class2 = SomeFunction();
        my_class2
                .SetA()
                .SetB();
        // destructor of `my_class2` here
    }

    // destructor of `my_class` here.
    return 0;
}
TylerH
  • 20,799
  • 66
  • 75
  • 101
User98
  • 31
  • 6

1 Answers1

0

In general the destructor is a good place if you want force that something happens even if an exception occured (but be aware that destructros are declared noexcept(true) by default).

I personally use it for "finally" blocks (with noexcept(false)). But usually in C++ you don't need finally because of RAII.

I think you can't prevent the life-time extension / local variables. And we have no attribute [[discard]], only [[nodiscard]].

But why you don't do the work in SetA()? For me it would be more clear?

A good reason would be if you need all the param data to do the work...

Update

There is one option. You could make your object not copyable / moveable:

    MyClass() = default;
    MyClass(const MyClass&) = delete;
    MyClass(MyClass&&) = delete;

But with such approach you can't have something like 'SomeFunction'. And of course such a factory function might causes a copy which call your destructor, too.


As a suggestion I would simply do it explicit:

SomeFunction()
            .SetA()
            .SetB()
            .Exec()
;
Bernd
  • 2,113
  • 8
  • 22