使用" auto"或模板类型扣除:"没有匹配函数来调用..."

时间:2017-09-11 00:18:17

标签: 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时遇到了麻烦。

如何解决此错误?

1 个答案:

答案 0 :(得分:0)

任何C ++标准都不允许使用auto作为函数参数类型。 (在一些版本的Concepts提案中,有可能,但是对于C ++ 2a,一段时间后接受的概念版本也不允许它。)

我相信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)声明视为两个独立类型。)