std :: enable_if和std :: shared_ptr

时间:2015-05-11 15:42:56

标签: c++ templates c++11

目标:让功能调度按预期工作。最小的示例代码应该说明一切。我想支持任务:命名任务,在自己的类中实现,以及使用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模板。示例中的注释行是我尝试过的。

  • 第一个不起作用,因为Callable的类型为std::shared_ptr<NamedTask>,而不是BaseTask的孩子。
  • 第二个也失败了,大概是因为std::shared_ptr<NamedTask>不是来自std::shared_ptr<BaseTask>

1 个答案:

答案 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