mardi 27 août 2019

C++11 template deduction fails when using std::function for parameter [duplicate]

Compiling with g++ 7.4.0, with --std=c++11 option, the following code works perfectly:

template<typename T, typename funcT>
size_t find_index( // wrapper over std::find_if to return the element index
    const std::vector<T>& v,
    funcT&& func // function type is a template
) {
    typename std::vector<T>::const_iterator it =
        std::find_if(v.cbegin(), v.cend(), std::move(func));
    return it == v.cend() ? -1 : it - v.cbegin();
}

int main() { // usage example
    std::vector<int> nums = {10, 20, 30};
    size_t x = find_index(nums,
        [](const int& i) -> bool { return i == 10; });
    return 0;
}

However, if I change the function signature to this:

// This is how I'd like to write the function!
template<typename T>
size_t find_index(
    const std::vector<T>& v,
    std::function<bool(const T&)>&& func // function type is explicit now!
) {
    typename std::vector<T>::const_iterator it =
        std::find_if(v.cbegin(), v.cend(), std::move(func));
    return it == v.cend() ? -1 : it - v.cbegin();
}

Template deduction fails, and I receive the error:

a.cpp: In function ‘int main()’:
a.cpp:30:57: error: no matching function for call to ‘find_index(std::vector<int>&, main()::<lambda(const int&)>)’
                [](const int& i) -> bool { return i == 10; });
                                                                            ^
a.cpp:8:12: note: candidate: template<class T> size_t find_index(const std::vector<T>&, std::function<bool(const T&)>&&)
    size_t find_index(
                ^~~~~~~~~~
a.cpp:8:12: note:   template argument deduction/substitution failed:
a.cpp:30:57: note:   ‘main()::<lambda(const int&)>’ is not derived from ‘std::function<bool(const T&)>’
                [](const int& i) -> bool { return i == 10; });

In the other hand, if I explicit the function call template parameter, it works:

// I don't want to have to write it this way...
size_t x = find_index<int>(nums, // note explicit <int> template parameter
    [](const int& i) -> bool { return i == 10; });

Why can't the compiler deduce the int template parameter? What am I missing?

Aucun commentaire:

Enregistrer un commentaire