Templates: "error: no type named 'value_type' in..."



  • Heyho,

    Ich möchte gern ein Template implementieren, das nachschauen soll, ob zwei std::maps sich gleichen.

    namespace STLContainerUtils
    {
      namespace Map
      {
        template<typename Key, typename Value>
        struct Predicate
        {
          bool operator() (std::pair<Key, std::shared_ptr<Value>> const &leftPair, std::pair<Key, std::shared_ptr<Value>> const &rightPair) const {
            return leftPair.first == rightPair.first;
            // TODO: wird noch erweitert mit booleschen Ausdrücken
          }
        };
    
        template<typename Key, typename Value>
        bool equalsKeyAndReferenceValue(std::map<Key, std::shared_ptr<Value>> const &leftMap, std::map<Key, std::shared_ptr<Value>> const &rightMap) {
          return leftMap.size() == rightMap.size()
                 && std::equal(leftMap.begin(), leftMap.end(), Predicate<Key, Value> {});
        }
      }
    }
    

    Leider bekomme ich folgende Fehlermeldung:

    STLContainerUtils.hpp:27:27:   required from 'bool STLContainerUtils::Map::equalsKeyAndReferenceValue(const std::map<Key, std::shared_ptr<_Tp> >&, const std::map<Key, std::shared_ptr<_Tp> >&) [with Key = unsigned int; Value = DialogOption]'
    DialogUnit.cpp:15:122:   required from here
    C:/PROGRA~1/MINGW-~1/X86_64~1.0-P/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_algobase.h:824:58: error: no type named 'value_type' in 'struct std::iterator_traits<STLContainerUtils::Map::Predicate<unsigned int, DialogOption> >'
           typedef typename iterator_traits<_II2>::value_type _ValueType2;
                                                              ^~~~~~~~~~~
    C:/PROGRA~1/MINGW-~1/X86_64~1.0-P/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_algobase.h:829:9: error: no type named 'value_type' in 'struct std::iterator_traits<STLContainerUtils::Map::Predicate<unsigned int, DialogOption> >'
           const bool __simple = ((__is_integer<_ValueType1>::__value
    

    Ich komme mit dieser Aussage des Compilers überhaupt nicht klar. Jede Hilfe wäre echt super 🙂



  • Entschuldige bitte meine Ignoranz, aber wann "gleichen sich" zwei std::maps?



  • In meinem Fall, wenn die Größen der Maps gleich sind und, wenn Key und Value sich jeweils gleichen.



  • @LynarStudios sagte in Templates: "error: no type named 'value_type' in...":

    wenn Key und Value sich jeweils gleichen.

    die Typen nehme ich an.





  • ich weiß nicht wirklich was du willst

    #include <map>
    #include <type_traits>
    #include <iostream>
    
    template<typename KEY, typename VALUE>
    bool is_equal(std::map<KEY, VALUE> const &first, std::map<KEY, VALUE> &second)
    {
    	return first.size() == second.size();
    }
    
    int main()
    {
    	std::map<int, char> foo;
    	std::map<int, char> bar;
    	std::cout << std::boolalpha << is_equal(foo, bar) << '\n';
    
    	std::map<int, double> qux;
    	std::cout << std::boolalpha << is_equal(foo, qux) << '\n';
    }
    


  • Na ich möchte das, was mein Code oben auch macht. Nur kompiliert es derzeitig nicht und ich kann nicht nachvollziehen warum. Dein Code ruft einfach nur eine template Methode auf.

    Ich möchte diese Funktionalität aber in std::equal als Prädikat mitgeben (Predicate).



  • Naja, wenn die Typen nicht passen kompiliert es nicht. Was erwartest du?



  • Eine Hilfestellung, die dazu führt, dass die Typen passen?



  • Wenn du deinem

    bool operator() (std::pair<Key, std::shared_ptr<Value>> const &leftPair, std::pair<Key, std::shared_ptr<Value>> const &rightPair) const {
    

    Typen gibst bei denen Key und Value nicht passen kompiliert es nicht. Punkt.



  • Deine Kommentare waren nicht wirklich hilfreich. Du hast mir lediglich das gesagt, was der Compiler auch gesagt hat.

    Die Typen haben ja in der "equalsKeyAndReferenceValue" Funktion gepasst. Sie wurden nur nicht richtig an die "Predicate" Funktion weiter gegeben und ich hätte das sehr gerne mittels std::equal gelöst. Meine Frage bezog sich darauf, wie ich das Prädikat abändern kann, damit es funktioniert. Das konntest Du mir leider nicht beantworten.

    Jetzt habe ich eine Hard-Code'd Version implementiert, die funktioniert.

    namespace STLContainerUtils
    {
      namespace Map
      {
        template<typename Key, typename Value>
        bool equalsKeyAndReferenceValue(std::map<Key, Value> const &leftMap, std::map<Key, Value> const &rightMap) {
          bool equals = leftMap.size() == rightMap.size();
          auto iterator = rightMap.begin();
    
          if(equals) {
            for(std::pair<Key, Value> entry : leftMap) {
              equals = entry.first == iterator->first && *entry.second.get() == *iterator->second.get();
              ++iterator;
    
              if(!equals) {
                break;
              }
            }
          }
    
          return equals;
        }
      }
    }
    


  • @LynarStudios sagte in Templates: "error: no type named 'value_type' in...":

    Deine Kommentare waren nicht wirklich hilfreich.

    Ja, ich hab' dich auch lieb. Wenn Key und Value nicht passen kompiliert es trotzdem nicht.



  • Wenn ich dich richtig verstanden habe, willst du sowas:

    template <typename T>
    bool mapsEqualValuesDereferenced(T m1, T m2) {
        if (m1.size() != m2.size()) return false;
        return std::equal(begin(m1), end(m1), begin(m2),
                          [](const auto &p1, const auto &p2){ return *p1.second == *p2.second; });
    
    }
    

    Bei deinem std::equal im ersten Post fehlt auf jeden Fall die rightMap als Parameter.



  • @wob Vielen dank, das war's 🙂



  • @LynarStudios sagte in Templates: "error: no type named 'value_type' in...":

    @wob Vielen dank, das war's 🙂

    Ähm, mir ist heute Nacht eingefallen, dass das wahrscheinlich nicht das richtige ist, weil ich oben gar nicht prüfe, ob die Keys aus gleich sind.

    Also das Lambda statt

    [](const auto &p1, const auto &p2){ return *p1.second == *p2.second; }
    

    das hier:

    [](const auto &p1, const auto &p2){ return p1.first == p2.first && *p1.second == *p2.second; }
    

Anmelden zum Antworten