我的程式碼可以混合蘋果和橘子嗎?
在您的 C 專案中,您使用大量「使用」來闡明變數的預期用途,主要用於 std::string 識別符,例如 PortalId 或 CakeId。您目前的方法允許以下操作:
using PortalId = std::string; using CakeId = std::string; PortalId portal_id("2"); CakeId cake_id("is a lie"); portal_id = cake_id; // OK
但這種靈活性是不可取的。您尋求編譯時類型檢查以防止混合不同的物件類型,同時保留原始物件的功能。
C 可以滿足此要求嗎?
是的,C 提供了解決方案為了你的困境。使用 C 17 和一些巧妙的編碼,可以建立一個防止混合類型的強型別識別碼。結果看起來像這樣:
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; }
在此程式碼中,不允許不同類型之間的賦值,向容器添加不相容的類型將導致編譯器錯誤。
什麼秘密?
魔法在於 SAFE_TYPEDEF 巨集。這是滿足您所有要求的更新版本:
#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& value() const { return _value; } private: std::string _value; // will only compare against same type of id. friend bool operator < (const string_id& l, const string_id& r) { return l._value < r._value; } friend bool operator == (const string_id& l, const string_id& r) { return l._value == r._value; } // and let's go ahead and provide expected free functions friend auto to_string(const string_id& r) -> const std::string& { return r._value; } friend auto operator << (std::ostream& os, const string_id& sid) -> std::ostream& { return os << sid.value(); } friend std::size_t hash_code(const string_id& 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& 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;
此程式碼定義了一個 string_id 類,用作強類型識別碼。它被標記為portal_tag 或cake_tag 以確保唯一性。該類別也重載了諸如
透過此實現,您可以強制執行強類型並防止在您的程式碼中混合類型。代碼。它涵蓋了您問題中提到的所有場景,並為您的需求提供了穩定的解決方案。
以上是C 可以幫助我防止在程式碼中混合蘋果和橘子嗎?的詳細內容。更多資訊請關注PHP中文網其他相關文章!