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

x33g5p2x  于 2024-01-09  发布在  其他
关注(0)|答案(1)|浏览(155)

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

  1. #include <iostream>
  2. #include <functional>
  3. #include <memory>
  4. template <class Type>
  5. void make_something(Type&& a){
  6. std::cout<<"Type&& overload"<<std::endl;
  7. }
  8. template <class Type>
  9. void make_something(std::function<Type()>){
  10. std::cout<<"std::function overload"<<std::endl;
  11. }
  12. int main(){
  13. make_something<int>(1); // prints "Type&& overload"
  14. make_something<int>(nullptr); // prints "std::function overload"
  15. make_something<int*>(nullptr); // prints "Type&& overload"
  16. using ptr_int = std::shared_ptr<int>;
  17. make_something<ptr_int>(nullptr); // prints "std::function overload" ... why?
  18. }

字符串

hgc7kmma

hgc7kmma1#

有一个从std::nullptr_tstd::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()>重载。
如果您要添加第三个更专门的重载,则会选择:

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

字符串
这通常在类型被推导时使用(例如,如果您调用make_something(std::function<int()>{}),如果没有模板规则,它将是模糊的),但当您指定模板参数时会出现这种意外行为。

相关问题