I would like to wrap member functions that conform to the type \'void (ClassType::Function)(ArgType)\' with a templated class. Later, I want to pass an instance of ClassType to
Reading over what you did made me think of a few options:
1) Wrap the instantiation in inheritance. This moves the scary stuff to your definition.
class FooWrapper : public Wrapper< double, Foo, &Foo::set >, public Foo { public: FooWrapper() : Wrapper(this){} };
Your logic code would looks like this:
FooWrapper fooWrapper;
fooWrapper.do_something(1.0);
std::cout << fooWrapper.get() << std::endl;
Which means you didn't eliminate the double template arguments, you just moved them.
2) There is a more generic way to wrap it, at one level:
template
class FooWrapper2 : public Wrapper, public classType1
{
public:
FooWrapper2()
: classType1(),
Wrapper(this)
{
}
};
This way has the draw-back of more complicated looking logic, but you don't have to define a new wrapper every time, just a new wrapper for every signature:
FooWrapper2 fooWrapper2;
fooWrapper2.do_something(1.0);
std::cout << fooWrapper2.get() << std::endl;
3) Keeping in line with the template idea, you can wrap the wrapper:
template
class FooWrapper3 : public FooWrapper2
{
public:
FooWrapper3()
{
}
};
The logic code from this looks a bit better, but you are stuck having to resubclass for each type you are wrapping (with specific code, instead of just using the template):
FooWrapper3 fooWrapper3;
fooWrapper3.do_something(1.0);
std::cout << fooWrapper3.get() << std::endl;
4) This option scraps the base wrapper class and uses an interface. Just pass the interfaces around as you would the wrappers and you can perform most actions.
template
class Do_something {
public:
virtual void do_something(ArgType value) = 0;
};
template
class FooWrapper4 : public Foo, public Do_something
{
public:
virtual void do_something(ArgType value)
{
set(1.0);
}
};
The test program I played with:
class Foo {
public:
Foo() : f_(0.0) {}
void set(double v) { f_ = v * 2.1; }
double get() { return f_; }
private:
double f_;
};
template
class Wrapper {
public:
explicit Wrapper(ClassType *cls) : cls_(cls) {}
void do_something(ArgType value) {
(cls_->*Method)(value);
}
private:
ClassType *cls_;
};
class FooWrapper : public Wrapper< double, Foo, &Foo::set >, public Foo
{
public:
FooWrapper() : Wrapper(this){}
};
template
class FooWrapper2 : public Wrapper, public classType1
{
public:
FooWrapper2()
: classType1(),
Wrapper(this)
{
}
};
template
class FooWrapper3 : public FooWrapper2
{
public:
FooWrapper3()
{
}
};
template
class Do_something {
public:
virtual void do_something(ArgType value) = 0;
};
template
class FooWrapper4 : public Foo, public Do_something
{
public:
virtual void do_something(ArgType value)
{
set(1.0);
}
};
#include
int main(int argc, char ** argv) {
Foo foo;
Wrapper wrapper(&foo);
wrapper.do_something(1.0);
std::cout << foo.get() << std::endl;
FooWrapper fooWrapper;
fooWrapper.do_something(1.0);
std::cout << fooWrapper.get() << std::endl;
// outputs "2.1"
FooWrapper2 fooWrapper2;
fooWrapper2.do_something(1.0);
std::cout << fooWrapper2.get() << std::endl;
FooWrapper3 fooWrapper3;
fooWrapper3.do_something(1.0);
std::cout << fooWrapper3.get() << std::endl;
FooWrapper4 fooWrapper4;
fooWrapper4.do_something(1.0);
std::cout << fooWrapper4.get() << std::endl;
return 0;
}