c++ - 带有 “auto”或模板类型推导的功能: “no matching function for call to…”

标签 c++ function pointers compiler-errors auto

假设我具有以下功能:

void mergesort(auto first, auto last) {
    if(last - first > 1) {
        auto middle = first + (last - first) /  2;
        merge_sort(first, middle);
        merge_sort(middle, last);
        std::inplace_merge(first, middle, last);
    }
}

我想将mergesort用作另一个函数的参数(也返回void)。

阅读其他一些SO问题之后,我尝试了以下方法:
void sort(auto args, std::function<void (auto, auto)> sorter) {
    // some stuff
    sorter(args.l.begin(), args.l.end());
    // some other stuff
}
// called by:
sort(args, mergesort);

并且。
void sort(auto args, void (*sorter)(auto, auto)) {
    sorter(args.l.begin(), args.l.end());
}
// called by:
sort(args, mergesort);

上面的尝试我也尝试改变指针等,以防万一我忘记了什么。

这些都不起作用,它们返回错误:
no matching function call to 'sort(p_args<long double>&, <unresolved overloaded function type>)'
args参数是模板化的结构,它工作正常,我在传递函数mergesort时遇到麻烦。

如何解决此错误?

最佳答案

任何C++标准都不允许将auto用作函数参数类型。 (在某些版本的Concepts提案中可能是这样,但不久前C++ 2a接受的Concepts版本也不允许这样做。)

我相信g++支持使用auto作为函数参数类型作为编译器扩展。这实际上所做的就是将一个函数转换为一个函数模板,其中每个auto都用模板类型参数替换。但这仅适用于实际的函数声明和函数定义。即使使用此编译器扩展,也无法创建指向void (*)(auto, auto)std::function<void(auto, auto)>函数的指针,因为在两种情况下,您都需要特定的函数类型,而不需要某种模板。

因此,您可能应该将代码更改为仅显式使用可移植的模板:

template <typename Iter>
void mergesort(Iter first, Iter last) { /*...*/ }

template <typename Args, typename Func>
void sort(Args& args, Func&& sorter) {
    std::forward<Func>(sorter)(args.l.begin(), args.l.end());
}

(请注意,我假设您可以对mergesort的两个参数强制使用相同的推导类型,尽管我相信g++会将原始void (auto, auto)声明视为两个独立的类型。)

关于c++ - 带有 “auto”或模板类型推导的功能: “no matching function for call to…” ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46146719/

相关文章:

c - 指针明显无缘无故地改变 - C

C: 在 Raspberry Pi 上写入数组指针时出现段错误

c++ - "already a friend"警告什么时候有用?

c++ - 编写可与多个版本的 Tcl 一起使用的 Tcl 扩展

c++ - 在 Windows `Can' t 打开包含文件时设置 CMake 和 vcpkg 时出错

c - 在 C 中从另一个函数调用一个函数时出错

javascript - (切换)函数未定义

c++ - 获取错误 "Debug Assertion Failed"

c - 将二维数组中的所有非零项保存到另一个一维数组中

c - 点作为数组索引