Search code examples
c++overload-resolutionperfect-forwarding

Select an overloaded non-template function with std::function parameter


I have both template and non-template member function overloaded like the code below:

struct TypeI {};
using FuncI = std::function<void(TypeI&)>;

struct TypeA {
    
    FuncI m_fn;
    
    TypeA(FuncI const& p_fn = nullptr){
        m_fn = p_fn;
    }
    
};

struct TypeX {
    
    void add_A(int p, FuncI const& p_func) {
        if (!p_func) return;
        //...some code
        add_A(p, TypeA{ p_func });
        //...some code
    }
    
    template<class T>
    void add_A(int p, T&& p_A) {
        this->getGroup(p).add(std::forward<T>(p_A));
        //...some code
    }   
}

int main(){
    
    TypeX x;
    x.add_A(100, [](TypeI& p_I){   //issue: this chooses the template add_A().
        //...some code
    });
    x.add_A(100, [](auto& p_I){    //issue: this chooses the template add_A().
        //...some code
    });
}

I need the non-template add_A() be selected, but the template version is selected instead. How to fix this?


Solution

  • The non-template version is taking std::function as parameter, and you're passing lambdas, which requires user-defined conversion. The template version is exact match and wins in overload resolution.

    You can impose restriction on the template parameter to make it unusable when object being passed could convert to FuncI.

    template<class T>
    std::enable_if_t<!std::is_convertible_v<T, FuncI>> add_A(int p, T&& p_A) {
    

    LIVE