Evgenii Legotckoi
Evgenii Legotckoi26. Februar 2019 05:22

SFINAE verwenden, um Vorlagenmethoden zu spezialisieren, abhängig vom Typ des Containers std::map oder std::vector, übergeben als Argument

Es gab ein Problem: "schreiben Sie eine zweite Implementierung der Vorlagenfunktion", bei der dieselben Argumente übergeben werden. Das heißt, die Signatur beider Funktionen ist vollständig gleich. Der Unterschied besteht darin, dass std::vector-Container und std::map-Container als Funktionsargumente übergeben werden können. Und je nachdem, ob es sich um einen std::vector oder eine std::map handelt, sollte die eine oder andere Implementierung gewählt werden.

In diesem Fall wird die SFINAE-Regel verwendet, die besagt: Wenn die letzten Argumenttypen einer überladenen Template-Funktion nicht ausgewertet werden können (Substitution von Template-Parametern durchführen), wirft der Compiler keinen Fehler, sondern sucht nach einer anderen geeigneten Überladung. Der Fehler tritt in drei Fällen auf:

  • Keine passende Überladung gefunden.
  • Es wurden mehrere solcher Überladungen gefunden, und C++ kann sich nicht entscheiden, welche genommen werden soll.
  • Es wurde eine Überladung erkannt, die sich als Vorlage herausstellte, und beim Instanziieren der Vorlage trat ein Fehler auf.

Unser Fall wird der zweite sein. Es gibt zwei Überladungsvorlagenfunktionen.


Implementierung

Um die erforderliche Überladung zu bestimmen, wird std::enable_if verwendet, das nur für solche Fälle verwendet wird, um eine bestimmte Funktion abhängig von der Art der zu verarbeitenden Daten zu spezialisieren.

Wie sich herausstellt, hat die Standardbibliothek STD keine Funktion, um festzustellen, ob ein Container eine std::map ist oder nicht. Aber auf StackOverflow wurde dieses Problem bereits diskutiert. Der dort angegebene Code muss nur ein wenig angepasst und korrekt angewendet werden, um die Spezialisierung von Funktionen je nach Containertyp zu schreiben.

Der Kern des Codes besteht darin, zur Kompilierzeit zu entscheiden, ob das Element des Containers ein std::pair ist, und basierend darauf zu entscheiden, ob der Container eine std::map ist. Wenn der Container std::map ist, wählen Sie eine Funktion aus; Wählen Sie andernfalls die zweite Implementierung der Funktion.

#include <iterator>
#include <type_traits>

// templates for determining whether the std::pair container element is
template <typename T>
struct is_pair : std::false_type {};

template <typename T, typename U>
struct is_pair<std::pair<T, U>> : std::true_type {};

template <typename T>
constexpr bool is_pair_v = is_pair<T>::value;

// templates for determining if the container is std::map
template<typename, typename = void>
struct is_mapping : std::false_type {};

template <typename Container>
struct is_mapping<Container, std::enable_if_t<is_pair_v<typename  std::iterator_traits<typename Container::iterator>::value_type>>> : std::true_type {};

template <typename T>
constexpr bool is_mapping_v = is_mapping<T>::value;

#include <map>
#include <vector>
#include <iostream>

class ClassWithSpecializedMethods
{
public:
    ClassWithSpecializedMethods() {}

    // A specialized method for handling std::map
    template <class ContainerType>
    static typename std::enable_if<is_mapping_v<ContainerType>, void>::type printContainer(ContainerType& container);

    // A specialized method for handling std::vector
    template <class ContainerType>
    static typename std::enable_if<!is_mapping_v<ContainerType>, void>::type printContainer(ContainerType& container);
};

// Method implementations
template <class ContainerType>
inline
static typename std::enable_if<is_mapping_v<ContainerType>, void>::type ClassWithSpecializedMethods::printContainer(ContainerType& container)
{
    std::cout << "Map:" << std::endl;
    for (const auto& [key, value] : container)
    {
        std::cout << "Key: " << key << " Value: " << value << std::endl;
    }
    std::cout << std::endl;
}

template <class ContainerType>
inline
static typename std::enable_if<!is_mapping_v<ContainerType>, void>::type ClassWithSpecializedMethods::printContainer(ContainerType& container)
{
    std::cout << "Vector:" << std::endl;
    for (const auto& value : container)
    {
        std::cout << "Value: " << value << std::endl;
    }
    std::cout << std::endl;
}

// Testing functions
int main() {
    std::cout << "is_pair:" << std::endl;
    std::cout << "Map:    " << is_pair_v<std::iterator_traits<std::map<int, int>::iterator>::value_type> << std::endl;
    std::cout << "Vector: " << is_pair_v<std::iterator_traits<std::vector<int>::iterator>::value_type>   << std::endl;
    std::cout << std::endl;
    std::cout << "is_mapping:" << std::endl;
    std::cout << "Map:    " << is_mapping_v<std::map<int, int>> << std::endl;
    std::cout << "Vector: " << is_mapping_v<std::vector<int>>   << std::endl;
    std::cout << std::endl;

    std::map<int, int> map_container = {{1, 1}, {2, 2}, {3, 3}};
    std::vector<int> vector_container = {1, 2, 3};

    ClassWithSpecializedMethods::printContainer(map_container);
    ClassWithSpecializedMethods::printContainer(vector_container);
}

C++-Standards verwendet

Damit dieser Code funktioniert, müssen Sie den C++17-Standard verwenden; Auf einem kleineren Standard wird der Code nicht kompiliert.

In QMake-Projekten sollten die folgenden Zeilen zur Profildatei hinzugefügt werden

CONFIG += console c++17
QMAKE_CXXFLA

## Conclusion

As a conclusion, we get the following conclusion


```lang-bsh
ist_paar:
Karte: 1
Vektor: 0

is_mapping:
Karte: 1
Vektor: 0

Karte:
Schlüssel: 1 Wert: 1
Schlüssel: 2 Wert: 2
Schlüssel: 3 Wert: 3

Vektor:
Wert: 1
Wert: 2
Wert: 3

Как это выглядит в консоли

Вывод с использование SFINAE для std::map и std::vector

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Stabiles Hosting des sozialen Netzwerks EVILEG. Wir empfehlen VDS-Hosting für Django-Projekte.

Magst du es? In sozialen Netzwerken teilen!

Kommentare

Nur autorisierte Benutzer können Kommentare posten.
Bitte Anmelden oder Registrieren
Letzte Kommentare
ИМ
Игорь Максимов5. Oktober 2024 07:51
Django – Lektion 064. So schreiben Sie eine Python-Markdown-Erweiterung Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas55. Juli 2024 11:02
QML - Lektion 016. SQLite-Datenbank und das Arbeiten damit in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssr8. Februar 2024 18:43
Qt Linux - Lektion 001. Autorun Qt-Anwendung unter Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
Qt WinAPI - Lektion 007. Arbeiten mit ICMP-Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVA25. Dezember 2023 10:30
Boost - statisches Verknüpfen im CMake-Projekt unter Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
Jetzt im Forum diskutieren
J
JacobFib17. Oktober 2024 03:27
добавить qlineseries в функции Пользователь может получить любые разъяснения по интересующим вопросам, касающимся обработки его персональных данных, обратившись к Оператору с помощью электронной почты https://topdecorpro.ru…
JW
Jhon Wick1. Oktober 2024 15:52
Indian Food Restaurant In Columbus OH| Layla’s Kitchen Indian Restaurant If you're looking for a truly authentic https://www.laylaskitchenrestaurantohio.com/ , Layla’s Kitchen Indian Restaurant is your go-to destination. Located at 6152 Cleveland Ave, Colu…
КГ
Кирилл Гусарев27. September 2024 09:09
Не запускается программа на Qt: точка входа в процедуру не найдена в библиотеке DLL Написал программу на C++ Qt в Qt Creator, сбилдил Release с помощью MinGW 64-bit, бинарнику напихал dll-ки с помощью windeployqt.exe. При попытке запуска моей сбилженной программы выдаёт три оши…
F
Fynjy22. Juli 2024 04:15
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …

Folgen Sie uns in sozialen Netzwerken