c++ - std::enable_if and std::shared_ptr -
goal: having function dispatching working intended. minimal example code should speak itself. want support tasks: named task, implemented in own class, , simpler task, specified using lambda. ideally, can converted std::function<void (void)> should work.
#include <iostream> #include <memory> #include <functional> // base class tasks class basetask { public: virtual void blah() = 0; }; // important enough tasks gets have // own class. class namedtask : public basetask { public: virtual void blah() { std::cout << "hey !" << std::endl; } }; // wrapper around simpler tasks. (lambda) class generictask : public basetask { public: generictask(const std::function<void (void)> fct) : fct_(fct) {} virtual void blah() override { fct_(); } private: std::function<void (void)> fct_; }; void enqueue(std::shared_ptr<basetask> t) { // store in queue. // we'll call here sake of example t->blah(); } template<typename callable> //typename std::enable_if<!std::is_base_of<basetask, callable>::value>::type //typename std::enable_if<!std::is_base_of<std::shared_ptr<basetask>, callable>::value>::type void enqueue(const callable &c) { auto t = std::make_shared<generictask>(c); t->blah(); } int main() { auto named = std::make_shared<namedtask>(); enqueue(named); // doesn't compile: tries call templated enqueue. enqueue([] () -> bool { std::cout << "lamda" << std::endl; }); } problem: don't manage write proper enable_if template. commented lines in example tried.
- the first 1 doesn't work because callable of type
std::shared_ptr<namedtask>, not child ofbasetask. - the second 1 fails too, presumably because
std::shared_ptr<namedtask>not derivestd::shared_ptr<basetask>.
you have 2 cases: callable convertible shared_ptr<basetask>, or not. checking base incorrect shared_ptr<namedtask> not related class hierarchy shared_ptr<basetask>, can construct shared_ptr<basetask> it.
that is:
// convertible shared_ptr<basetask> void enqueue(std::shared_ptr<basetask> t); // not convertible shared_ptr<basetask> template<typename callable> typename std::enable_if< !std::is_convertible<callable, std::shared_ptr<basetask>>::value >::type enqueue(const callable &c); alternatively, can think of 2 cases constructible/not constructible:
template<typename callable> typename std::enable_if< !std::is_constructible<std::shared_ptr<basetask>, callable>::value >::type enqueue(const callable &c); third alternative condition function template enqueue on callable 0 arguments:
template<typename callable> auto enqueue(const callable &c) -> decltype(c(), void())
Comments
Post a Comment