C++11 Wrapper Class

J

jz bnk

Suppose I wanted to extend the interface of an arbitrary base class
reference in C++11, while still preserving the original interface. I
could accomplish this as follows:

template <typename T>
class Wrapper : public T
{
public:
Wrapper (T& base)
: T(std::move(base)),
original(base)
{
}

~Wrapper ()
{
original = std::move(static_cast <T&> (*this));
}

void f () {}

private:
T& original;
};

I'm not particularly happy with the above design - aside from the obvious
implicit lifetime constraints Wrapper requires any other references to
base are invalidated for the duration of lifetime (although their use
should still be well-formed if I understand move-semantics here).
Ideally, Wrapper should not alter base - something similar to the
following would suffice:

template <typename T>
class Wrapper
{
public:
Wrapper (T& base)
: reference(base)
{
}

~Wrapper ()
{
original = std::move(static_cast <T&> (*this));
}

template <typename... Args>
auto g (Args... args) ->
decltype(std::declval <T> ().g(std::forward <Args> (args...)))
{
return reference.g(std::forward <Args> (args...));
}

void f () {}

private:
T& reference;
};

provided the names and const correctness of the methods exposed by T were
known a priori, which I can't assume. Is there a better pattern I could
be using here? If not, is the first Wrapper class well-formed and are
there additional concerns I've overlooked there?

My use-case for this sort of construct is a serialization function - a
parent container's read/write function is called to serialize a
collection of sub-objects. Some of the sub-objects require additional
data provided by the Wrapper construct, the remaining sub-objects need
to function properly when used with or without the wrapper. Something
along the lines of the following would be a reasonable facsimile here:

template <typename Child>
struct reader <Container <Child>>
{
template <typename Input, typename Output>
static bool read (Input& in, Output& out)
{
Wrapper w_in(in);
return reader <Child>::read(w_in, out);
}
};
 
S

SG

Am 17.12.2012 04:12, schrieb Luca Risolia:
template <typename... Args>
auto g(Args&&... args) ->
decltype(std::declval <T> ().g(std::forward <Args> (args)...)) {
// g must not be void(...)
return this->get().g(std::forward <Args > (args)...);
}

Regarding your comment: Try compiling this:

void g();

void f()
{
return g();
}

:)
 
M

molw5.iwg

On 16/12/2012 11:57, jz bnk wrote:

See if this Wrapper fits your needs. There are no additional concerns
other the ones you already know.

I'm afraid not - I don't know in advance what function names need to be
forwarded from the Wrapper class to the base class, nor the const
correctness of those methods. However, I appreciate the correction - I
hadn't realized my forwarders were moving rvalue references :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top