目标:让功能调度按预期工作。最小的示例代码应该说明一切。我想支持任务:命名任务,在自己的类中实现,以及使用lambda指定的更简单的任务。理想情况下,任何可以转换为std::function<void (void)>
的内容都应该有效。
#include <iostream>
#include <memory>
#include <functional>
// A Base class for my tasks
class BaseTask
{
public:
virtual void blah() = 0;
};
// An important enough tasks that it gets to have its
// own class.
class NamedTask : public BaseTask
{
public:
virtual void blah()
{
std::cout << "Hey !" << std::endl;
}
};
// A 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 just call it here for the sake of the 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 to call the templated enqueue.
enqueue([] () -> bool { std::cout << "Lamda" << std::endl; });
}
问题:我没有设法编写正确的enable_if
模板。示例中的注释行是我尝试过的。
std::shared_ptr<NamedTask>
,而不是BaseTask
的孩子。std::shared_ptr<NamedTask>
不是来自std::shared_ptr<BaseTask>
。答案 0 :(得分:3)
您有两种情况:您的可调用可转换到shared_ptr<NamedTask>
,或不是。检查基数不正确,因为shared_ptr<BaseTask>
与shared_ptr<BaseTask>
的类层次结构无关,但您可以从中构建// is convertible to shared_ptr<BaseTask>
void enqueue(std::shared_ptr<BaseTask> t);
// is NOT convertible to shared_ptr<BaseTask>
template<typename Callable>
typename std::enable_if<
!std::is_convertible<Callable, std::shared_ptr<BaseTask>>::value
>::type
enqueue(const Callable &c);
。
那是:
template<typename Callable>
typename std::enable_if<
!std::is_constructible<std::shared_ptr<BaseTask>, Callable>::value
>::type
enqueue(const Callable &c);
或者,您可以将这两种情况视为可构造/不可构造的:
enqueue
第三种方法是在任何可用零参数调用的函数上调整函数模板template<typename Callable>
auto enqueue(const Callable &c) -> decltype(c(), void())
:
guest:guest