为什么模板类型扣除失败?

时间:2014-12-30 19:13:34

标签: c++ templates c++11 condition-variable type-deduction

为什么在下面的代码中,模板类型是否无法从最后一个参数自动推断出来,就像它在std::condition_variable::wait中那样?

template< typename Predicate >
    //requires Truth< Predicate >
class lock_monitor_guard
{
public:
    lock_monitor_guard( std::mutex& mutex, std::condition_variable& monitor, Predicate predicate );
    ~lock_monitor_guard();

private:
    std::unique_lock<std::mutex> lock;
    std::condition_variable& monitor;
};

template< typename Predicate >
    //requires Truth< Predicate >
lock_monitor_guard<Predicate>::lock_monitor_guard( std::mutex& mutex, std::condition_variable& monitor, Predicate predicate )
    : lock( mutex ), monitor( monitor )
{
        monitor.wait<Predicate>( lock, predicate );
}

template< typename Predicate >
    //requires Truth< Predicate >
lock_monitor_guard<Predicate>::~lock_monitor_guard()
{
        lock.unlock();
        monitor.notify_one();
}

当我尝试构建像lock_monitor_guard guard( jobs_mutex, jobs_monitor, ([]()->bool{return true;}) );这样的行时,我收到一条错误消息:use of class template 'lock_monitor_guard' requires template arguments。但为什么 ?为什么它适用于STL std::condition_variable::wait。谢谢你的帮助!

2 个答案:

答案 0 :(得分:6)

类型的模板参数无法推断,期间。这是因为类型特化可以提供完全不同的成员集,因此在您知道类型的模板参数之前,您甚至不知道可用的构造函数。

这就是标准库具有辅助函数的原因,如std::make_pair。在构造或引用std::pair时,必须指定类型参数(std::pair<int, double>(1, 2.0)),但在大多数情况下,可以在调用函数时推导出它们(std::make_pair(1, 2.0)) 。 (请注意,std::condition_variable::wait是一个函数,而不是一个类型。)

如果为lock_monitor_guard类型实现移动构造函数,则可以创建一个与std::make_pair精神相似的辅助函数,然后使用auto复制初始化来提供演绎。 (请注意,您还必须调整析构函数,以解释this移动构造函数使其内容“被盗”的可能性。)

template <typename Predicate>
lock_monitor_guard<Predicate> create_lock_monitor_guard(
    std::mutex & mutex,
    std::condition_variable & monitor,
    Predicate && predicate)
{
    return lock_monitor_guard<Predicate>(mutex, monitor, std::forward<Predicate>(predicate));
}

auto guard = create_lock_monitor_guard(
    jobs_mutex,
    jobs_monitor,
    [] { return true; });

答案 1 :(得分:2)

您可以传递如下所示的类型。

template< typename Predicate >
        //requires Truth< Predicate >
    class lock_monitor_guard
    {
    public:
        lock_monitor_guard( std::mutex& mutex, std::condition_variable& monitor, Predicate predicate );
    };


auto pred = [] { return true; };

lock_monitor_guard<decltype(pred)> l(jobs_mutex, jobs_monitor, pred);

std::condition_variable::wait是函数而不是类型因此会自动推导出类型。