具有 "auto" 或模板类型推导的函数:"no matching function for call to..."

Function with "auto" or template type deduction: "no matching function for call to..."

假设我有函数:

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 作为另一个函数的参数(也 returning 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);

以上尝试我还尝试更改指针等,以防万一我忘记了什么。

None 这些工作,他们 return 错误:

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) 声明视为两个独立的类型.)