I have a class Door
that implements a method LockCheck()
, and a class Stove
with a method BurnerCheck()
. I want a class House
that takes as a constructor argument either Door::LockCheck
or Stove::BurnerCheck
along with an unknown set of args for the given function. House
would then store the function and its args such that it can call them at some later time. For example,
auto stove = Stove();
auto stove_check = stove.BurnerCheck;
auto burner_args = std::make_tuple<bool, bool>(true, false);
auto house = House(burner_args, stove_check);
// do some other stuff...
house.check_safety(); // internally calls stove.BurnerCheck(burner_args)
What should class House
"looks" like?
So far I have,
template <typename ReturnType, typename... Args>
class House {
public:
House(Args... args, std::function<ReturnType(Args...)> func)
: input_args_(std::forward_as_tuple(args...)),
safety_func_(func) {}
};
private:
Args... input_args_; // Is this the correct declaration?
std::function<ReturnType(Args...)> safety_func_;
};
Notes:
Some preliminary considerations.
1) If you write a template class
House
where the argument of the check methods are "unknown" (and, I suppose, different from type to type) you have to know that arguments when you define the
House
objects and you have differentHouse
types (oneHouse
type forDoor
's checks, oneHouse
type forStove
's checks, etc.) and (before C++17) you can't declareHouse
object simply asbut you have to explicit the template types; something as
Suggestion: in you are not interested in the
ReturnType
of the checks methods (and if you can ignore it) makeHouse
a not-template class and make a variadic template constructor for it; something as2) If you have a template function/method/constructor with a some fixed arguments and a variadic list of arguments, place the variadic list of arguments in last position, so the compiler can deduce the variadic list of types from arguments and there is no need of explicit it.
So the preceding constructor become something as
3) As far I know, there is no way to pass a pointer to an actual method to a function o to a variable; so no
and no
stove_check
as argument ofHouse
constructor.The usual way that I know for this sort of problem is pass the object (
stove
) and a pointer toBurnerCheck
method referred to the class, not to the object; something asNow the contructor become
and you can call the
BurnerCheck()
method ofstove
asNow my suggested
House
class: a class with astd::function<void(void)>
member that is initialized, inHouse
constructor, with a lambda that capture object, pointer method and arguments.And a
check_safety()
method that simply call that member.Something as follows
The following is a full working example
If you're interested in the value returned from the checked method... I suppose you can make
House
a template class with only theReturnType
parameter and adjust the class consequently.You can store all the arguments as a tuple. You can then call
safety_func_
by unpacking the tuple into function arguments. The unpacking can directly be done in C++17 using std::apply.For a pure C++11 tuple unpacking solution, see this post