【问题标题】:Template argument deduction fails on lambda using tuple使用元组的 lambda 模板参数推导失败
【发布时间】:2014-03-11 18:14:12
【问题描述】:

我正在尝试创建一个查询函数,让我可以查询 STL 容器的某些元素特征,然后返回结果集。它实际上只是围绕正常 STL 操作(特别是 copy_if 和 back_inserter)的语法糖。

#include <string>
#include <tuple>
#include <functional>
#include <vector>

// This is the query function, it compiles fine
template<typename T, typename ... U>
T query(T const& input, std::function<bool(std::tuple<U...> const& row)> pred)
{
    T result;
    std::copy_if(std::begin(input), std::end(input), std::back_inserter(result), pred);
    return result;
}

// Define my Row, with each column having a type
using Row = std::tuple<int, float, std::string>;

int main()
{
    // Create a sample vector of Rows
    std::vector<Row> vec;
    for(size_t i = 0; i < 100; ++i)
        vec.emplace_back(i, 5.0f, "hello");

    // This is how I would perform the query 
    // **** This is the line that doesn't compile due to template arg deduction failure ****
    auto result = query(vec, [](Row const& row) -> bool { return true; });
    return 0;
}

这是编译器输出(Clang 3.3)

main.cpp:27:19: error: no matching function for call to 'query'
    auto result = query(vec, [](Row const& row) -> bool { return true; });
                  ^~~~~
main.cpp:8:3: note: candidate template ignored: failed template argument deduction
T query(T const& input, std::function<bool(std::tuple<U...> const& row)> pred)
  ^
1 error generated.

【问题讨论】:

    标签: c++ templates lambda tuples template-argument-deduction


    【解决方案1】:

    lambda 不是std::function,它是一个重载operator() 的类类型,两者是不同的类型。 query 函数需要 std::function&lt;...&gt; 参数,而模板参数推导需要类型完全匹配(除了 cv 限定符),因此从 lambda 表达式到 std::function 的转换永远不会被推导。

    当然,一种解决方案是在调用query之前构造一个std::function

    auto result = query(vec, 
                        std::function<bool(Row const&)>(
                            [](Row const&) { return true; }));
    

    另一种选择是改变你的功能本身

    template<typename T, typename UnaryPredicate>
    T query(T const& input, UnaryPredicate&& pred)
    {
        T result;
        std::copy_if(std::begin(input), std::end(input), 
                     std::back_inserter(result), std::forward<UnaryPredicate>(pred));
        return result;
    }
    

    现在可以使用您的原始代码调用它。

    Live demo

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-05
      • 1970-01-01
      • 2012-10-26
      • 2012-12-06
      相关资源
      最近更新 更多