Korri
Korri

Reputation: 571

Is there a way to make member function NOT callable from constructor?

I have member function (method) which uses

std::enable_shared_from_this::weak_from_this() 

In short: weak_from_this returns weak_ptr to this. One caveat is it can't be used from constructor. If somebody would use my function from constructor of inherited class, weak_from_this inside it would return expired weak_ptr. I guard against that with assertion checking that it's not expired, but it's a run-time check.

Is there a way to check against it at compile time?

Upvotes: 21

Views: 2370

Answers (3)

einpoklum
einpoklum

Reputation: 131656

Not as such, but - if performance is not an issue, you could add a flag which indicates construction is complete, and use that to fail at run-time with such calls:

class A {

    // ... whatever ...
public:
    A() { 
        // do construction work
        constructed = true;
    }

    foo() {
        if (not constructed)  { 
            throw std::logic_error("Cannot call foo() during construction"); 
        }
        // the rest of foo
    }

protected:
    bool constructed { false };
}

You could also make these checks only apply when compiling in DEBUG mode (e.g. with conditional compilation using the preprocessor - #ifndef NDEBUG) so that at run time you won't get the performance penalty. Mind the noexcepts though.

An alternative to throwing could be assert()'ing.

Upvotes: 4

Guillaume Racicot
Guillaume Racicot

Reputation: 41780

No there is no way. Consider:

void call_me(struct widget*);

struct widget : std::enable_shared_from_this<widget> {
    widget() {
        call_me(this);
    }

    void display() {
        shared_from_this();
    }
};

// later:

void call_me(widget* w) {
    w->display(); // crash
}

The thing is there is a reason you want to check for not calling shared_from_this in the constructor. Think about that reason. It's not that shared_from_this cannot be called, it's because it's return value has no way of being assigned yet. It is also not because it will never be assigned. It's because it will be assigned later in the execution of the code. Order of operation is a runtime property of your program. You cannot assert at compile time for order of operation, which is done at runtime.

Upvotes: 5

I am afraid the answer is "no, it's not possible to protect against this at compile-time." It's always difficult to prove a negative, but consider this: if it was possible to protect a function this way, it would probably have been done for weak_from_this and shared_from_this in the standard library itself.

Upvotes: 16

Related Questions