c++ - C++14 中的模板化函数参数

标签 c++ templates lambda c++14 std-function

此代码无法编译,甚至在 C++14 下也无法编译,因为模板类型推导存在问题。最不优雅的解决方法是什么?

#include <vector>
#include <functional>
#include <iostream>

template <class T>
std::vector<T> merge_sorted(
    const std::vector<T>& a, const std::vector<T>& b,
    std::function<bool(const T, const T)> a_before_b)
{
    std::vector<T> ret;
    auto ia=a.begin();
    auto ib=b.begin();
    for (;;ia!=a.end() || ib!=b.end())
        ret.push_back( a_before_b(*ia,*ib) ? *(ia++) : *(ib++) );
    return ret;
}

int main()
{
    std::vector<double> A { 1.1, 1.3, 1.8 };
    std::vector<double> B { 2.1, 2.2, 2.4, 2.7 };
    auto f = [](const double a, const double b) -> bool {
        return (a-(long)(a))<=(b-(long(b))); };
    std::vector<double> C = merge_sorted(A, B, f);
    for (double c: C)
        std::cout << c << std::endl;
    // expected outout: 1.1 2.1 2.2 1.3 2.4 2.7 1.8
}

这里是来自 g++ -std=c++14 main.cpp 的错误信息:

main.cpp: In function ‘int main()’:
main.cpp:23:49: error: no matching function for call to ‘merge_sorted(std::vector<double>&, std::vector<double>&, main()::<lambda(double, double)>&)’
     std::vector<double> C = merge_sorted(A, B, f);
                                                 ^
main.cpp:6:16: note: candidate: template<class T> std::vector<T> merge_sorted(const std::vector<T>&, const std::vector<T>&, std::function<bool(T, T)>)
 std::vector<T> merge_sorted(
                ^~~~~~~~~~~~
main.cpp:6:16: note:   template argument deduction/substitution failed:
main.cpp:23:49: note:   ‘main()::<lambda(double, double)>’ is not derived from ‘std::function<bool(T, T)>’
     std::vector<double> C = merge_sorted(A, B, f);

==

稍后编辑,仅作记录:这里有一个代码版本可以编译(感谢收到的答案)并正确执行(对上述未经测试的代码进行了多次更正):

#include <vector>
#include <functional>
#include <iostream>

template <class T, class Pred>
std::vector<T> merge_sorted(const std::vector<T>& a, const std::vector<T>& b, Pred a_before_b)
{
    std::vector<T> ret;
    auto ia=a.begin();
    auto ib=b.begin();
    for (;ia!=a.end() && ib!=b.end();)
        ret.push_back( a_before_b(*ia,*ib) ? *(ia++) : *(ib++) );
    for (;ia!=a.end();)
        ret.push_back( *(ia++) );
    for (;ib!=b.end();)
        ret.push_back( *(ib++) );
    return ret;
}

int main()
{
    std::vector<double> A { 1.1, 1.3, 1.8 };
    std::vector<double> B { 2.1, 2.2, 2.4, 2.7 };
    auto f = [](const double a, const double b) -> bool {
        return (a-(long)(a))<=(b-(long(b))); };
    std::vector<double> C = merge_sorted(A, B, f);
    for (double c: C)
        std::cout << c << std::endl;
    // expected outout: 1.1 2.1 2.2 1.3 2.4 2.7 1.8
}

最佳答案

这里的问题是 f不是 std::function .它是一些未命名的类类型,但它不是 std::function .当编译器进行模板参数推导时,它不会进行任何转换,它会按原样使用参数来推导它们的类型。这意味着它希望看到 std::function<bool(const T, const T)> 的地方它看到 main()::<lambda(double, double)>因为那是 lambda 的类型,并且由于这些类型不匹配,因此推导失败。为了使演绎成功,您需要让它们匹配。

在不更改函数签名的情况下,您必须转换 fstd::function为了让它工作。看起来像

std::vector<double> C = merge_sorted(A, B, static_cast<std::function<bool(const double,const double)>>(f));

如果您不介意更改函数签名,那么我们可以使用

template <class T, class Func>
std::vector<T> merge_sorted(
    const std::vector<T>& a, const std::vector<T>& b,
    Func a_before_b)

现在您是否传递 std::function 都没关系了或 lambda 或仿函数。

关于c++ - C++14 中的模板化函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42673106/

相关文章:

c++ - SFINAE 检查失败

c++ - 使用 -std=c++0x 导致错误 : ‘Iterator’ does not name a type error

c# - 更改 LambdaExpression 中的参数名称只是为了显示

c++ - 如何将模板父类(super class)类型传递给模板基类?

node.js - 如何下载图像并将S3放入lambda Nodejs中

c++ - 当简单捕获中的标识符显示为参数的声明符 ID 时,没有编译器诊断

c++ - 实时操作系统调度员

c++ - vector 中 pair 元素的数据类型是什么?

c++ - fgets() 似乎没有正确移动文件指针

c++ - QSlider、QTimer 和 valueChanged 用法