Justin R.
Justin R.

Reputation: 24021

Using function calls in constructor initializers

Imagine that I have a class with a member that does some work on a vector when it's instantiated, and the class does not have a default constructor:

struct Header
{
    static const Header & Read(uint8_t * & buffer, size_t & length);
    Header( some params );
}

class C
{
private:
    std::shared_ptr<std::vector<uint8_t>> mBuffer;

public:
    Header header;

    C(std::shared_ptr<std::vector<uint8_t>> p_buffer) :
        mBuffer(p_buffer),
        header(Header::Read(p_buffer->data(), p_buffer->size()))
    {}
};

This quite reasonably fails to compile, as data() and size() are not lvalues.

I could add additional member variables to represent the vector's first element and length, and pass those to Read():

class C
{
private:
    std::shared_ptr<std::vector<uint8_t>> mBuffer;
    uint8_t * head;
    size_t length;

public:
    Header header;

    C(std::shared_ptr<std::vector<uint8_t>> p_buffer) :
        mBuffer(p_buffer),
        head(p_buffer->data()),
        length(p_buffer->size()),
        header(Header::Read(head, length))
    {}
};

But this seems awfully hokey. Is there a clean way to do this?

Upvotes: 1

Views: 77

Answers (1)

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726509

This looks like a straightforward problem with the signature of the header(...) requiring lvalues for its parameters. This can be fixed by adding a static function that calls through to the original header without requiring lvalues, like this:

class C
{
private:
    std::shared_ptr<std::vector<uint8_t>> mBuffer;
    static const Header& ReadStatic(uint8_t *buffer, size_t length) {
        // You can call Header::Read now, because when it comes to passing lvalues,
        // function parameters are fair game:
        return Header::Read(buffer, length);
    }
public:
    Header header;

    C(std::shared_ptr<std::vector<uint8_t>> p_buffer) :
        mBuffer(p_buffer),
        header(ReadStatic(p_buffer->data(), p_buffer->size()))
    {}
};

This lets you get rid of the two members that were actually stand-in temporaries that you added for the purpose of calling Header::Read.

Upvotes: 1

Related Questions