Heim >Backend-Entwicklung >C++ >Kann C mir helfen, das Mischen von Äpfeln und Orangen in meinem Code zu verhindern?

Kann C mir helfen, das Mischen von Äpfeln und Orangen in meinem Code zu verhindern?

Barbara Streisand
Barbara StreisandOriginal
2024-11-16 07:55:03444Durchsuche

 Can C   Help Me Prevent Mixing Apples and Oranges in My Code?

Kann mein Code Äpfel und Orangen mischen?

In Ihrem C-Projekt verwenden Sie zahlreiche „Usings“, um den beabsichtigten Zweck von Variablen zu verdeutlichen , hauptsächlich für std::string-Bezeichner wie PortalId oder CakeId. Ihr aktueller Ansatz ermöglicht Folgendes:

using PortalId = std::string;
using CakeId   = std::string;

PortalId portal_id("2");
CakeId cake_id("is a lie");

portal_id = cake_id; // OK

Aber diese Flexibilität ist unerwünscht. Sie streben eine Typprüfung zur Kompilierungszeit an, um eine Vermischung verschiedener Objekttypen zu verhindern und gleichzeitig die Funktionalität des ursprünglichen Objekts beizubehalten.

Kann C diese Anforderung erfüllen?

Ja, C bietet eine Lösung für dein Dilemma. Mit C 17 und etwas cleverer Codierung ist es möglich, einen stark typisierten Bezeichner zu erstellen, der das Mischen von Typen verhindert. Die Ergebnisse sehen etwa so aus:

SAFE_TYPEDEF(std::string, PortalId);
SAFE_TYPEDEF(std::string, CakeId);

int main()
{
    PortalId portal_id("2");
    CakeId cake_id("is a lie");
    std::map<CakeId, PortalId> p_to_cake; // OK

    p_to_cake[cake_id]   = portal_id; // OK
    p_to_cake[portal_id] = cake_id;   // COMPILER ERROR

    portal_id = cake_id;        // COMPILER ERROR
    portal_id = "1.0";          // COMPILER ERROR
    portal_id = PortalId("42"); // OK
    return 0;
}

In diesem Code sind Zuweisungen zwischen verschiedenen Typen nicht zulässig und das Hinzufügen inkompatibler Typen zu Containern führt zu Compilerfehlern.

Was ist das Geheimnis?

Die Magie liegt im Makro SAFE_TYPEDEF. Hier ist die aktualisierte Version, die alle Ihre Anforderungen erfüllt:

#include <iostream>
#include <string>
#include <map>
#include <unordered_map>

// define some tags to create uniqueness
struct portal_tag {};
struct cake_tag {};

// a string-like identifier that is typed on a tag type
template<class Tag>
struct string_id
{
    using tag_type = Tag;

    // needs to be default-constuctable because of use in map[] below
    string_id(std::string s) : _value(std::move(s)) {}
    string_id() : _value() {}

    // provide access to the underlying string value
    const std::string&amp; value() const { return _value; }
private:
    std::string _value;

    // will only compare against same type of id.
    friend bool operator < (const string_id&amp; l, const string_id&amp; r) {
        return l._value < r._value;
    }

    friend bool operator == (const string_id&amp; l, const string_id&amp; r) {
        return l._value == r._value;
    }

    // and let's go ahead and provide expected free functions
    friend
    auto to_string(const string_id&amp; r)
    -> const std::string&amp;
    {
        return r._value;
    }

    friend
    auto operator << (std::ostream&amp; os, const string_id&amp; sid)
    -> std::ostream&amp;
    {
        return os << sid.value();
    }

    friend
    std::size_t hash_code(const string_id&amp; sid)
    {
        std::size_t seed = typeid(tag_type).hash_code();
        seed ^= std::hash<std::string>()(sid._value);
        return seed;
    }

};

// let's make it hashable

namespace std {
    template<class Tag>
    struct hash<string_id<Tag>>
    {
        using argument_type = string_id<Tag>;
        using result_type = std::size_t;

        result_type operator()(const argument_type&amp; arg) const {
            return hash_code(arg);
        }
    };
}


// create some type aliases for ease of use
using PortalId = string_id<portal_tag>;
using CakeId = string_id<cake_tag>;

using namespace std;

Dieser Code definiert eine string_id-Klasse, die als stark typisierte Kennung dient. Es ist entweder mit portal_tag oder cake_tag getaggt, um die Einzigartigkeit sicherzustellen. Die Klasse überlädt auch Operatoren wie <, „==" und freie Funktionen wie to_string, << und hash_code.

Mit dieser Implementierung können Sie eine starke Typisierung erzwingen und das Mischen von Typen in Ihrem verhindern Code. Es deckt alle Szenarien ab, die Sie in Ihrer Frage erwähnt haben, und bietet eine stabile Lösung für Ihre Anforderungen.

Das obige ist der detaillierte Inhalt vonKann C mir helfen, das Mischen von Äpfeln und Orangen in meinem Code zu verhindern?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn