Maison > développement back-end > C++ > le corps du texte

C peut-il m'aider à éviter de mélanger des pommes et des oranges dans mon code ?

Barbara Streisand
Libérer: 2024-11-16 07:55:03
original
387 Les gens l'ont consulté

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

Mon code peut-il mélanger des pommes et des oranges ?

Dans votre projet C, vous utilisez de nombreux "usings" pour clarifier le but recherché des variables , principalement pour les identifiants std::string comme PortalId ou CakeId. Votre approche actuelle permet ce qui suit :

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

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

portal_id = cake_id; // OK
Copier après la connexion

Mais cette flexibilité n'est pas souhaitable. Vous recherchez une vérification de type au moment de la compilation pour éviter de mélanger différents types d'objets tout en préservant les fonctionnalités de l'objet d'origine.

C peut-il répondre à cette demande ?

Oui, C fournit une solution pour votre dilemme. En utilisant C 17 et un codage intelligent, il est possible de créer un identifiant fortement typé qui empêche le mélange des types. Les résultats ressemblent à ceci :

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;
}
Copier après la connexion

Dans ce code, les affectations entre différents types ne sont pas autorisées et l'ajout de types incompatibles aux conteneurs entraînera des erreurs de compilation.

Qu'est-ce que le secret ?

La magie réside dans la macro SAFE_TYPEDEF. Voici la version mise à jour qui répond à tous vos besoins :

#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;
Copier après la connexion

Ce code définit une classe string_id qui sert d'identifiant fortement typé. Il est étiqueté avec portal_tag ou cake_tag pour garantir son unicité. La classe surcharge également les opérateurs comme <, "==" et les fonctions gratuites telles que to_string, << et hash_code.

Avec cette implémentation, vous pouvez appliquer un typage fort et empêcher le mélange des types dans votre code. Il couvre tous les scénarios que vous avez mentionnés dans votre question et fournit une solution stable pour vos besoins.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal