我的代码可以混合苹果和橙子吗?
在您的 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中文网其他相关文章!