c++ - 强制 C++ 更喜欢带有隐式转换的重载而不是模板

标签 c++ c++11 templates implicit-conversion overload-resolution

我有一种情况,我需要重载解析来更喜欢带有隐式转换的重载而不是同名的模板函数。
考虑以下示例:

#include <iostream>
#include <functional>

void call_function(const std::function<void()>& function)
{
   std::cout << "CALL FUNCTION 1" << std::endl;
   function();
}

template <typename Function>
void call_function(const Function& function)
{
    std::cout << "CALL FUNCTION 2" << std::endl;
    function();
}

int main()
{
    // Pass a lambda to "call_function"
    // This lambda is implicitly convertible to 'std::function<void()>'
    // Even though it is implicitly convertible, the template function is selected by the compiler.
    call_function([]{
        std::cout << "TEST" << std::endl;
    });
}
输出:
CALL FUNCTION 2
TEST
不幸的是,编译器似乎检测到 call_function 的第一个实现将需要隐式转换将我传递的 lambda 转换为 std::function<void()>对象,因此它确定模板版本是更好的匹配并使用模板。我需要强制编译器更喜欢隐式转换重载而不是模板,因此输出将是:
CALL FUNCTION 1
TEST
我怎样才能做到这一点? (另请注意,我只能使用符合 C++11 的编译器,因此我无法使用 C++14 及更高版本的功能)

最佳答案

重载解析永远不会喜欢隐式转换而不是精确匹配。由于模板将始终完全匹配,因此选择非模板的唯一方法是确保它也不需要任何转换。
为此,您可以首先将闭包(lambda 表达式的结果)转换为正确的类型:

    call_function(static_cast<std::function<void()>>([]{
        std::cout << "TEST" << std::endl;
    }));
现在传递的正是第一个重载(“FUNCTION 1”)所采用的类型,因此将选择该类型。
也就是说,如果您关心调用的是哪个,您可能不应该使用重载。重载通常应保留用于重载本质上等效的情况,因此您真的不关心调用哪个。

关于c++ - 强制 C++ 更喜欢带有隐式转换的重载而不是模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66037162/

相关文章:

c++ - 静态断言实例化时模板类型的大小

C++ boost 示例 : Creating and Managing Threads (Compilation Error)

c++ - 编译时等效的 std::cout,或 c++11 中编译时常量值的 static_assert 字符串化

c++ - std::remove 与 vector::erase 和未定义的行为

c++ - 如何修复 C++ 线程死锁示例

c++ - 在 C++ 编译时计算和打印阶乘

c++ - 使用 placement new 正确分配数组

c++ - __FILE__ 编译时的宏操作处理

c++ - C++ 类的问题

c++ - 将数组指针/引用发送到模板