[Erledigt] Type Deduction von Templates
-
Hallo,
ich habe erfolgreich für Collection-Typen wiestd::vector
undQVector
ein Collection Trait fürpush_back()
implementiert:#include <type_traits> #include <string> #include <vector> struct CollectionTrait { public: template <template<typename, typename...> class Collection, typename ValueType, typename... Rest, typename ReturnType> CollectionTrait (ReturnType (Collection<ValueType, Rest...>::*)(ValueType&&)) { } }; int main() { CollectionTrait insertMethod(&std::vector<std::string>::push_back); return 0; }
Nun hätte ich gerne ähnliches für Maps für die insert Methode machen:
#include <type_traits> #include <string> #include <map> struct MapRegistration { template <template <typename, typename, typename...> class MapT, typename KeyType, typename ValueType, typename... Rest, typename ReturnType, typename Map = MapT<KeyType, ValueType, Rest...>> MapRegistration(ReturnType (MapT<KeyType, ValueType, Rest...>::*insertMethod)(KeyType&&, ValueType&&)) { } }; int main() { MapRegistration stdMapStringDoubleRegistration2(&std::map<std::string, double>::insert_or_assign); return 0; }
Allerdings erhalte ich folgenden Fehler:
<source>:15:21: error: no matching constructor for initialization of 'MapRegistration' 15 | MapRegistration stdMapStringDoubleRegistration2(&std::map<std::string, double>::insert_or_assign); | ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ <source>:5:8: note: candidate constructor (the implicit copy constructor) not viable: no overload of 'insert_or_assign' matching 'const MapRegistration' for 1st argument 5 | struct MapRegistration | ^~~~~~~~~~~~~~~ <source>:5:8: note: candidate constructor (the implicit move constructor) not viable: no overload of 'insert_or_assign' matching 'MapRegistration' for 1st argument 5 | struct MapRegistration | ^~~~~~~~~~~~~~~ <source>:8:5: note: candidate template ignored: couldn't infer template argument 'MapT' 8 | MapRegistration(ReturnType (MapT<KeyType, ValueType, Rest...>::*insertMethod)(KeyType&&, ValueType&&)) | ^ 1 error generated. Compiler returned: 1
Weiß hier jemand weiter?
Für den Hintergrund: Das wird ein Meta Type System, mit Dynamischen Collections und Dynamischen Maps, mit denen man über Runtime Reflection Operationen ausführen kann.
Danke im Voraus!
Liebe Grüße
Steffo
-
Ich konnte das Problem auf folgende Weise lösen:
#include <type_traits> #include <string> #include <map> struct MapRegistration { template <template <typename, typename, typename...> class MapT, typename KeyType, typename ValueType, typename... Rest, typename Map = MapT<KeyType, ValueType, Rest...>> MapRegistration(ValueType& (MapT<KeyType, ValueType, Rest...>::*insertMethod)(KeyType const&)) { } }; int main() { MapRegistration stdMapStringDoubleRegistration2(&std::map<std::string, double>::operator[]); return 0; }
-
Hallo,
ich bins nochmal.
Leider merke ich gerade, dass der Code nicht unter Visual Studio kompiliert.Ich habe die Methode leicht umgeschrieben, damit der Fehler klarer wird:
#include <type_traits> #include <string> #include <map> struct MapRegistration { template <template <typename, typename, typename...> class MapT, typename KeyType, typename ValueType, typename... Rest, typename Map = MapT<KeyType, ValueType, Rest...>> static void from(ValueType& (MapT<KeyType, ValueType, Rest...>::*insertMethod)(KeyType const&)) { } }; int main() { MapRegistration::from(&std::map<std::string, double>::operator[]); return 0; }
Der VS Compiler sagt hier:
<source>(15): error C2672: 'MapRegistration::from': no matching overloaded function found <source>(8): note: could be 'void MapRegistration::from(ValueType &(__cdecl MapT<KeyType,ValueType,Rest...>::* )(const KeyType &))' <source>(15): note: 'void MapRegistration::from(ValueType &(__cdecl MapT<KeyType,ValueType,Rest...>::* )(const KeyType &))': could not deduce template argument for 'MapT' <source>(15): note: 'void MapRegistration::from(ValueType &(__cdecl MapT<KeyType,ValueType,Rest...>::* )(const KeyType &))': could not deduce template argument for 'KeyType' <source>(15): note: 'void MapRegistration::from(ValueType &(__cdecl MapT<KeyType,ValueType,Rest...>::* )(const KeyType &))': could not deduce template argument for 'ValueType' Compiler returned: 2
Wie kann ich dem Compiler die richtige überladene Methode beibringen?
-
Es funktioniert, wenn man explizit die Template-Parameter angibt: C++ Compiler Explorer Code
MapRegistration2::from<std::map, std::string, double>(&std::map<std::string, double>::operator[]);
Evtl. hat die Standard C++ Library Implementation beim MSVC einen überladenen
operator []
oder aber die Template-Parameter beistd::map<...>
sind dort (leicht) anders deklariert? Schau doch mal in dessen Headerdatei<map>
.
-
@Th69 Danke, für deine Antwort. Ich bin auf diese Lösung ebenfalls gekommen. Tatsächlich wurde mir aber auf Stackoverflow dringend von dieser Lösung abgeraten, da das undefiniertes Verhalten sei. Soll heißen, dass sich die Implementierung jederzeit ändern kann.
Ich bin dann auf eine andere Lösung gekommen, wo ich praktisch ein vordefiniertes Lambda übergebe. Die Lösung sieht so ähnlich wie der Vorschlag eines Stackoverflow-Users.