Reputation: 932
I'm writing a template wrapper, something like this
template<class T>
class Wrapper{
public:
Wrapper(T data);
~Wrapper();
void doSomeWrapperWork();
private:
T data;
};
If I want to access the wrapped data, I can obviously add a getter function that returns a reference to the data. I was wondering however if there is anyway, with some template magic, to call directly on the wrapper functions of the underlying wrapped data. In other words, if I have a class TestObject
with a public function void foo()
, I would like to be able to call it in this way:
Wrapper<TestObject> myWrapper;
myWrapper.foo();
instead of:
myWrapper.getData().foo();
without knowing a priori that such a function exists. Is this possible?
Upvotes: 1
Views: 147
Reputation: 155
Yes, try something like
#include <iostream>
struct TestObject{
void foo() { std::cout << "TestObject" << std::endl;}
};
template <class T>
struct Wrapper : public T{
Wrapper() {}
void doSomeWrapperWork() {}
};
int main() {
Wrapper<TestObject> wrapper;
wrapper.foo();
}
This allows you to add more functionality as need while still allowing the wrapper to be used as a class T.
This is inspired by the decorator design pattern.
Upvotes: 1
Reputation: 41092
Not quite, until C++ gets reflection we can't easily write wrapper classes without a lot of boilerplate macros
but
You can add an implicit conversion of your wrapper class to T
:
template<class T>
class Wrapper{
public:
Wrapper(T data_) : data(data_) {}
operator const T&() const
{
return data;
}
private:
T data;
};
And now your class is convertible to T
, so we can call a method on T
, with a little work:
usage:
struct Foo
{
constexpr int bar() const
{
return 42;
}
};
int main()
{
constexpr Foo f;
Wrapper<Foo> my_wrapper(f);
static_assert(static_cast<const Foo&>(my_wrapper).bar() == 42);
}
If you want to avoid the casting yourself, you can write a free function that will call your function, so that implicit conversion may take over:
int call_bar(const Foo& f)
{
return f.bar();
}
Usage:
Foo f;
Wrapper<Foo> my_wrapper(f);
std::cout << call_bar(my_wrapper); // 42
I kind of like this approach as all it requires is that we add a free function for each wrapped function we want instead of having to manually do a bunch of casting.
Upvotes: 1