Detekcja typu dla drugiego parametru

Detekcja typu dla drugiego parametru
Marius.Maximus
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2239
0

Jak ten kod poprawić aby nie trzeba było jawnie podawać typu dla drugiego parametru tylko kompilator sam zrobił konwersję typów

Kopiuj
#include <algorithm>            // std::lower_bound
#include <vector>
#include <string>
#include <cstdint>

// indeks najblizszej wartosci dla zadanego "x"
// na podstawie https://alexsm.com/cpp-closest-lower-bound/
template <typename F>
size_t search_closest(const std::vector<F>& sorted_array, F x)
{
    auto iter_geq = std::lower_bound(
        sorted_array.begin(),
        sorted_array.end(),
        x
    );

    if (iter_geq == sorted_array.begin()) {
        return 0;
    }

    double a = *(iter_geq - 1);
    double b = *(iter_geq);

    if (std::abs(x - a) < std::abs(x - b)) {
        return iter_geq - sorted_array.begin() - 1;
    }

    return iter_geq - sorted_array.begin();
}

int main()
{
    std::vector<uint32_t>  v_uint32_t;
    std::vector<int32_t>  v_int32_t;

    auto testInt = search_closest(v_int32_t,1);
    auto testUInt = search_closest(v_uint32_t,1); // tutaj kompilator powinien sie domyślić ze chce zamienić int -> uint32_t
    // auto testUInt = search_closest(a.readVectorU32("a"),(uint32_t)1);
    return 0;
}

https://godbolt.org/z/4d3qYc1Kd

<source>:38:33: error: no matching function for call to 'find_closest(std::vector<unsigned int="int">&, int)' 38 | auto testUInt = find_closest(v_uint32_t,1); | ~~~~~~~~~~~~^~~~~~~~~~~~~~
SL
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1102
2

Dodaj kolejny typ template <typename F, typename X>. W tym wypadku piszesz jak byk, że typ ma być taki sam

MarekR22
  • Rejestracja: dni
  • Ostatnio: dni
3

Jeśli wolisz zapobiec detekcji typu na drugim argumencie:
To C++20 ma std::type_identity_t:

Kopiuj
template <typename F>
size_t find_closest(const std::vector<F>& sorted_array, std::type_identity_t<F> x)

https://godbolt.org/z/5Efd7a5jn

We wcześniejszych wersjach C++ można zrobić tak:

Kopiuj
template <typename F>
size_t find_closest(const std::vector<F>& sorted_array, typename std::vector<F>::value_type x)

https://godbolt.org/z/1EEbTGP9E

albo samemu zaimplementować odpowiednik std::type_identity_t:

Kopiuj
template<typename T>
struct type_identity
{
    using type = T;
};
template<typename T>
using type_identity_t = typename type_identity::type;

Przy okazji ten warunek z std::abs wygląda bardzo podejrzanie. Dla typów bez znaku na pewno nie będzie działał poprawnie.
Jako, że używasz std::lower_bound znaczy się dane są posortowane, ergo ten std::abs nie jest potrzebny, trzeba tylko skorzystać z faktu, że znamy relacje pomiędzy a, x, b:
a &lt; x \le b
W sumie kolejny dowód na to, że nie wszystko co w internecie się świeci jest godne zaufania.

MarekR22
  • Rejestracja: dni
  • Ostatnio: dni
1

Znalazłem poważnego bug-a w tym kodzie i to nie związanego z abs: https://godbolt.org/z/nWdT3hYfx
Klasyczny buffer overflow.

Wersja poprawiona: https://godbolt.org/z/j9zKMMGYz

Bug z abs nie wyszedł w moich testach, bo po drodze jest konwersja na double co jest brzydkim hackiem, który częściowo ukrywa ten bug.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.