2

In the example below, why does the last one calls the function overload with std::function as parameter?

#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?
}

1 Answer 1

4

There is an implicit conversion from std::nullptr_t to both std::shared_ptr<int> and std::function<std::shared_ptr<int>()>.

This means that calling make_something<ptr_int>(nullptr) needs to do the same amount of conversions to transform the std::nullptr_t argument into the function argument (a user-defined conversion sequence).

If these were both non-template functions, this would be ambiguous. Since they are templates, the tiebreakers for templates can be used.

std::function<Type()> is more specialised than Type (cv- and ref- qualifications are discarded for this check). This means that std::function<Type()> overload is chosen.

If you were to add a third more specialized overload, that would be chosen:

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

This is generally used when the type is deduced (e.g., if you called make_something(std::function<int()>{}), it would be ambiguous without the template rules), but has this unexpected behaviour when you specify the template argument.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.