Frage zu enable_if als Templateparameter



  • Hiho,

    ich brauche einen Vergleich in einer Klasse. Diese ist als Template geschrieben und kann entweder floats oder integer haben. Bei einem- Float-Vergleich möchte ich eine kleine Abweichung zulassen, wo zwei Zahlen immer noch als gleich gelten. Daher habe ich mir die Methode 'is_equal' geschrieben, einmal für Fließkommazahlen und einmal für Integer

    auto it = std::find_if(points.begin(), points.end(), [&point](auto& data) { return (is_equal(data[0], point[0]) &&
    																					is_equal(data[1], point[1]) &&
    																					is_equal(data[2], point[2])); });
    
    ...
    
    //
    template<typename U = std::enable_if<std::is_floating_point<U>::value>::type>
    static bool is_equal(U left, U right)
    {
    	return (std::abs(left - right) < epsilon);
    }
    
    //
    template<typename U = std::enable_if<std::is_integral<U>::value>::type>
    static bool is_equal(U left, U right)
    {
    	return (left == right);
    }
    

    Mein VS2015 meckert nun:

    error C2535: "bool matrem::Kd_tree<T,Dimension>::is_equal(U,U)": Memberfunktion bereits definiert oder deklariert

    Ist an meinem Code etwas falsch, oder meckert das VS hier zu unrecht? An sich sollte doch eine der beiden Methoden durch SFINAE wegfallen, sodass nur eine übrigbleibt und es keine Mehrdeutigkeiten gibt!?



  • Was glaubst du denn welchen Typ du dem Parameter U zuweist?



  • float oder integer. Das ganze kompiliert aber auch nicht, wenn ich es auf http://en.cppreference.com im Browser kompilieren will. Also hab ich da irgendwo noch einen Anwendungs-/Denkfehler



  • Guck mal auf http://en.cppreference.com/w/cpp/types/enable_if und suche nach "A common mistake". Lustigerweise haben die genau denselben Anwendungsfall wie du brauchst 😉



  • Wie kann ich das dann sinnvoll machen?



  • Naja, z.B. so:

    #include <type_traits>
    #include <iostream>
    #include <cmath>
    
    template <typename T,
              typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
    bool equal(T a, T b) {
        std::cout << "int\n";
        return a == b;
    }
    
    template <typename T,
              typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
    bool equal(T a, T b) {
        std::cout << "float\n";
        return std::abs(a - b) < 0.0001;
    }
    
    int main() {
        equal(7, 42);
        equal(7., 42.);
        equal(8.f, 23.f);
        equal(9ull, 10ull);
    }
    


  • Da kommt bei mir das raus:

    error C2672: "matrem::Kd_treematrem::Voxel\_surfaces\_obj\_exporter2::Vertex\_data,3::is_equal": keine übereinstimmende überladene Funktion gefunden


Anmelden zum Antworten