Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Bolehkah C Membantu Saya Mencegah Mencampurkan Epal dan Oren dalam Kod Saya?

Bolehkah C Membantu Saya Mencegah Mencampurkan Epal dan Oren dalam Kod Saya?

Barbara Streisand
Barbara Streisandasal
2024-11-16 07:55:03390semak imbas

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

Bolehkah Kod Saya Mencampurkan Epal dan Oren?

Dalam projek C anda, anda menggunakan banyak "penggunaan" untuk menjelaskan tujuan pembolehubah yang dimaksudkan , terutamanya untuk pengecam std::string seperti PortalId atau CakeId. Pendekatan semasa anda membenarkan perkara berikut:

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

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

portal_id = cake_id; // OK

Tetapi fleksibiliti ini tidak diingini. Anda mencari semakan jenis masa kompilasi untuk mengelakkan pencampuran jenis objek yang berbeza sambil mengekalkan kefungsian objek asal.

Bolehkah C Memenuhi Permintaan Ini?

Ya, C menyediakan penyelesaian untuk dilema anda. Menggunakan C 17 dan beberapa pengekodan pintar, anda boleh mencipta pengecam ditaip kuat yang menghalang jenis pencampuran. Hasilnya kelihatan seperti ini:

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;
}

Dalam kod ini, penetapan antara jenis yang berbeza tidak dibenarkan dan menambah jenis yang tidak serasi pada bekas akan mengakibatkan ralat pengkompil.

Apa Rahsianya?

Keajaiban terletak dalam makro SAFE_TYPEDEF. Berikut ialah versi terkini yang mengendalikan semua keperluan anda:

#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;

Kod ini mentakrifkan kelas string_id yang berfungsi sebagai pengecam yang ditaip kuat. Ia ditag dengan sama ada portal_tag atau cake_tag untuk memastikan keunikan. Kelas ini juga melebihkan operator seperti <, "==" dan fungsi percuma seperti to_string, <<, dan hash_code.

Dengan pelaksanaan ini, anda boleh menguatkuasakan penaipan yang kuat dan menghalang jenis pencampuran dalam anda kod. Ia merangkumi semua senario yang anda nyatakan dalam soalan anda dan menyediakan penyelesaian yang stabil untuk keperluan anda.

Atas ialah kandungan terperinci Bolehkah C Membantu Saya Mencegah Mencampurkan Epal dan Oren dalam Kod Saya?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn