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);
}
};
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);
}
};