为什么我的函数超载不是我的模板优先?

Hol*_*olt 4 c++ templates overload-resolution c++11

根据这个问题的第一个答案:函数模板重载,"非模板化(或"模板化程度较低")重载优于模板".

#include <iostream>
#include <string>
#include <functional>

void f1 (std::string const& str) {
    std::cout << "f1 " << str << std::endl;
}

template <typename Callback, typename... InputArgs>
void call (Callback callback, InputArgs ...args) {
    callback(args...);
}

void call (std::function<void(std::string const&)> callback, const char *str) {
    std::cout << "custom call: ";
    callback(str);
}

int main() {
    auto f2 = [](std::string const& str) -> void {
        std::cout << "f2 " << str << std::endl;
    };

    call(f1, "Hello World!");
    call(f2, "Salut Monde !");

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

其中,据我了解,的第二个定义call是"非模板",因而应在当我做的第一个选择call(f1, "1")call(f2, "2").

事实并非如此,我得到以下输出:

f1 Hello World!
f2 Salut Monde !
Run Code Online (Sandbox Code Playgroud)

如果我删除模板版本call,我得到预期的输出.

call在这种情况下,为什么我的超载没有超过第一个?

Nia*_*all 6

需要用户定义的转换类型,f1f2不是std::function用户定义的转换,因此选择模板版本.

如果你确实提供了call一个与函数指针完全匹配的函数,例如;

void call (void(*callback)(std::string const&), const char *str)
Run Code Online (Sandbox Code Playgroud)

它会被选中f1.


注意:通过在+lambda上添加一元,你也可以在这种情况下获得一个函数指针(你的捕获列表为空)...

auto f2 = +[](std::string const& str) -> void
//        ^ unary +
Run Code Online (Sandbox Code Playgroud)