带有std::function类型参数、nullptr值和shared_ptr类型的函数模板重载

问题描述 投票:0回答:1

下面的例子中,为什么最后一个调用的是以std::function为参数的函数重载?

#include <iostream>
#include <functional>
#include <memory>

template <class Type>
void make_something(Type&& a){
    std::cout<<"Type&& overload"<<std::endl;
}

template <class Type>
void make_something(std::function<Type()>){
    std::cout<<"std::function overload"<<std::endl;
}


int main(){ 
    make_something<int>(1);  // prints "Type&& overload"
    make_something<int>(nullptr);  // prints "std::function overload"
    make_something<int*>(nullptr);  // prints "Type&& overload"

    using ptr_int = std::shared_ptr<int>;
    make_something<ptr_int>(nullptr);  // prints "std::function overload" ... why?
}
c++ templates overloading std-function overload-resolution
1个回答
1
投票

存在从

std::nullptr_t
std::shared_ptr<int>
std::function<std::shared_ptr<int>()>
的隐式转换。

这意味着调用

make_something<ptr_int>(nullptr)
需要执行相同数量的转换才能将
std::nullptr_t
参数转换为函数参数(用户定义的转换序列)。

如果这些都是非模板函数,那么这将是不明确的。由于它们是模板,因此可以使用模板的决胜局。

std::function<Type()>
Type
更专业(此检查忽略 cv- 和 ref- 资格)。这意味着选择了
std::function<Type()>
过载。

如果您要添加第三个更专业的重载,则会选择:

template <class Type>
void make_something(std::function<Type*()>){
    std::cout<<"std::function Type* overload"<<std::endl;
}

这通常在推导类型时使用(例如,如果您调用

make_something(std::function<int()>{})
,如果没有模板规则,它将是不明确的),但是当您指定模板参数时,会出现这种意外的行为。

© www.soinside.com 2019 - 2024. All rights reserved.