Why it was not possible to derive a template argument when passing a lambda instead of a function pointer

I have a bubble sort function that takes an array, a comparison function, and a boolean that indicates whether to sort the array in reverse order. This is a template function that supports any type of data and automatically displays the size of the array.

When specifying a comparison function, if I pass a pointer to a function, the compiler will automatically select the data type of the array, which is great. But if I pass the lambda instead, it will not be output automatically. I have to specify the data type explicitly, or static_castlambda as fnCompare_t<double>.

What is the reason for this? Because according to this post , as long as the lambda does not capture, it can be used as a pointer to a plain old function, but it seems like this is not always the case? Why can this be different in this case?

#include <iostream>
using namespace std;

template <typename T>
using fnCompare_t = int(*)(T const &, T const &);

template <typename T, size_t count>
inline void BubbleSort(
    T(&array)[count],
    fnCompare_t<T> fnCompare,
    bool reverse)
{
    cout << "TODO: Implement BubbleSort" << endl;
}

double doubleArray[] = {
    22.3, 11.2, 33.21, 44.2, 91.2, 15.2, 77.1, 8.2
};

int CompareDouble(double const & a, double const & b)
{
    return a > b ? 1 : a == b ? 0 : -1;
}

int main()
{
    auto fnCompare = [](double const & a, double const & b) -> int {
        return a > b ? 1 : a < b ? -1 : 0;
    };
    // compile OK:
    BubbleSort(doubleArray, CompareDouble, false);
    BubbleSort(doubleArray, static_cast<fnCompare_t<double>>(fnCompare), false);
    BubbleSort<double>(doubleArray, fnCompare, false);
    // compile error, could not deduce template argument:
    //BubbleSort(doubleArray, fnCompare, false);
    return 0;
}
+4
source share
2 answers

The reason is that you cannot get an implicit template conversion when using a deduction. Classic example:

template <class T>
T min(T x, T y);

Calling this function min(1, 3.0)will result in a failure. Because for both arguments, he tries to find T, to get a perfect match, and fails. If you explicitly specify a template parameter, it can work: min<double>(1, 3.0). The same is true in your example, if you explicitly specify Tit will work.

:

template <typename Iter, typename F>
inline void BubbleSort(
    Iter b, Iter e,
    F fnCompare,
    bool reverse)

. , :

template <typename T, size_t count, typename F>
inline void BubbleSort(
    T(&array)[count],
    F fnCompare,
    bool reverse);

std::array C, .

, "" , , . ++, , , . , , , : lambdas . , , !

, . . , ( , ).

+5

lambda . . static_cast ing + , , + :

BubbleSort(doubleArray, +fnCompare, false);
//                      ^^
//     applying unary + invokes the function pointer conversion operator

, , , , (. this ). , , .

+1

Source: https://habr.com/ru/post/1675446/


All Articles