Reputation: 24021
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
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