我不想写 town->first
我想写 town->name
。内联命名访问器(重命名地图迭代器的第一个和第二个和命名 std::pair 成员)是迄今为止我发现的最佳解决方案。我对命名访问器的问题是类型安全性的丧失:
pair
可以参考struct { int index;双值; }
或 struct { int Population;双平均温度; }
。任何人都可以提出一种简单的方法,也许类似于特征的方法?
我经常想从函数返回一个对或一个元组,引入像 struct city { string name; 这样的新类型是相当累人的。 int 邮政编码; } 及其每次的构造函数。我很高兴了解 boost 和 C++0x,但我需要一个没有 boost 的纯 C++03 解决方案。
更新
关于andrewdski的问题:是的,像pair
这样的(假设的)语法将创建与pair
可以满足您的要求。我什至不介意必须实现一次自定义对/元组模板类,并在需要新类型时适当地向其传递“名称特征”模板参数。我不知道“名字特征”会是什么样子。也许这是不可能的。
Instead of writing town->first
I would like to write town->name
. Inline named accessors (Renaming first and second of a map iterator and Named std::pair members) are the best solutions I have found so far. My problem with named accessors is the loss of type safety:
pair<int,double>
may refer to struct { int index; double value; }
or to struct { int population; double avg_temp; }
. Can anyone propose a simple approach, perhaps something similar to traits?
I often want to return a pair or a tuple from a function and it is quite tiring to introduce a new type like struct city { string name; int zipcode; }
and its ctor every time. I am thrilled to learn about boost and C++0x but I need a pure C++03 solution without boost.
Update
Re andrewdski's question: yes, a (hypothetical) syntax like pair<int=index, double=value>
which would create a distinct type from pair<int=population, double=avg_temp>
would meet your requirement. I do not even mind having to implement a custom pair/tuple template class ONCE and just passing a 'name traits' template argument to it approprietly when I need a new type. I have no idea how that 'name traits' would look like. Maybe it's impossible.
发布评论
评论(10)
我不知道你还能做得比
“没有什么是不重要的”更好。您需要两个成员的类型,您的整个问题是围绕为两个成员命名而构建的,并且您希望它是唯一的类型。
您确实了解聚合初始化语法,对吗?您不需要构造函数或析构函数,编译器提供的就可以了。
示例:
http://ideone.com/IPCuw类型安全要求您引入新类型,否则
pair
在 (name, zipcode) 和 (population, temp) 之间不明确。在 C++03 中,返回一个新元组需要:
或编写一个方便的构造函数:
来获取
但是,在 C++0x 中,您将被允许编写
并且不需要用户定义的构造函数。
I don't see how you can possibly do better than
There's nothing non-essential there. You need the types of the two members, your whole question is predicated around giving names to the two members, and you want it to be a unique type.
You do know about aggregate initialization syntax, right? You don't need a constructor or destructor, the compiler-provided ones are just fine.
Example:
http://ideone.com/IPCuwType safety requires that you introduce new types, otherwise
pair<string, int>
is ambiguous between (name, zipcode) and (population, temp).In C++03, returning a new tuple requires either:
or writing a convenience constructor:
to get
With C++0x, however, you will be allowed to write
and no user-defined constructor is necessary.
我想详细说明
是最接近您要寻找的内容的,尽管
struct City { string name; int 邮政编码; }
看起来完全没问题。I guess elaborating on
is the closest you get to what youre looking for, althrough
struct City { string name; int zipcode; }
seems perfectly fine.虽然不完美,但可以使用标记数据:
但正如 Ben Voigt 所说: struct city { string name; int 邮政编码; }; 几乎总是会更好。
编辑:模板可能是一种矫枉过正,您可以在命名空间中使用自由函数。这仍然无法解决类型安全问题,因为任何
std::pair
与任何其他std::pair
的类型相同:Although not perfect, it is possible to use tagged data:
But as Ben Voigt says:
struct city { string name; int zipcode; };
would pretty much always be better.EDIT: Templates probably are an overkill, you could use free functions in a namespace instead. This still does not solve type safety issues, as any
std::pair<T1, T2>
are the same type as any otherstd::pair<T1, T2>
:由于
std::pair
通常用于在std::map
容器中存储条目,因此您可能需要查看 Boost 中的标记元素Bimap。概要:
请注意,bimap 可以透明地模拟
std::map
或其他关联容器类型,而无需牺牲性能;他们只是更加灵活。在这个特定的示例中,定义很可能最好更改为以下内容:我邀请您浏览 Boost Bimap 的文档以了解完整情况
Since
std::pair
is commonly used for storing entries instd::map
containers, you might want to look at tagged elements in Boost Bimap.Synopsis:
Note that bimaps can transparently emulate
std::map
or other associative container types without performance cost; They just are more flexible. In this particular example, the definition would most likely best be changed into something like:I invite you to wander around the documentation for Boost Bimap to get the full picture
您可以使用指向成员的指针运算符。有几种选择。这是最直接的。
您可以将一种伪类型的访问器放入专用的
命名空间
中,以将它们与其他事物分开。那么它看起来像my_map_value.*zip::name
。但是,除非您确实需要使用pair
,否则定义一个新的struct
可能会更容易。You can use pointer-to-member operators. There are a few alternatives. Here is the most straightforward.
You can put the accessors for one pseudo-type into a dedicated
namespace
to separate them from other things. Then it would look likemy_map_value.*zip::name
. But, unless you really need to use apair
, it's probably easier to just define a newstruct
.我想出了一个
Utility_pair
宏,可以这样使用:时,您可以这样做:
然后,每当您需要访问
ValidityDateRange
的字段 执行:I came up with a
Utility_pair
macro that can be used like this:Then, whenever you need to access the fields of
ValidityDateRange
, you can do it like this:This is the implementation:
可能不值得额外的内存,但如果您想保留 std::pair 或 std::tuple 的优势/保持与不可更改的 API 的兼容性,您可以继承然后定义对其成员的引用。
除了内存成本之外,这还带来了一个巨大的警告,即 STL 类型通常没有虚拟析构函数,因此如果您尝试使用指向基类型的指针取消分配,可能会导致内存泄漏:
或者,也许最好如上所述通过 @holyblackcat,在许多情况下,只要您不尝试遵守特定的不可更改的 API,您也可以为您的结构定义
std::get(PairShadow)
的重载需要std::pair
或std::tuple
Probably not worth the extra memory, but if you want to retain the advantage of
std::pair
orstd::tuple
/ maintain compatibility with an unchangeable API, you can inherit from them and then define references to their members.Apart from the memory cost, this comes with the giant caveat that STL types generally don't have virtual destructors and can thus cause memory leaks if you attempt to de-allocate using a pointer to the base type:
Alternatively, and perhaps preferrably as mentioned by @holyblackcat you could also just define an overload to
std::get<int>(PairShadow)
for your struct in many cases as long as you aren't trying to conform to an unchangable API which specifically requires astd::pair
orstd::tuple
老问题,但添加了 C++17 的更新,您可以在其中使用 结构化绑定声明< /a> 用于命名 std::pair 和 std::tuple 的成员。例如:
注意:这不涉及类型安全方面。
Old question, but adding an update for C++17 where you can use Structured binding declaration for naming the members of std::pair and std::tuple. For example:
Note: This doesn't address the type safety aspect.
我认为你真的应该在这里引入新类型。在拥有pair类方面,我完全站在stl一边,但这正是java人认为他们不想拥有pair类的确切原因,并且你应该总是为你的类似piar的类型引入新类型。
stl 解决方案的好处是您可以使用通用类对,但只要您确实希望以与第一/第二不同的方式命名成员,您就可以引入新的类型/类。除此之外,引入新类还可以让您在必要时轻松添加第三个成员。
I think you should really introduce new types here. I am totally on stl's side in terms of having a pair class, but this is the exact reason why java people argue they don't want to have a pair class and you should always introduce new types for your piar-like types.
The good thing about the stl solution is that you can use the gerneric class pair, but you can introduce new types / classes whenever you really want members to be named in a different way than first/second. On top of that introducing new classes gives you the freedom of easily adding a thrid member if it should ever become necessary.
也许您可以从pair继承您自己的pair类,并在构造函数中设置两个名为name和zipcode的引用(只需确保实现您将使用的所有构造函数)
perhaps you can inherit your own pair class from pair and set two references called name and zipcode in your constructor ( just be sure to implement all constructors you will use )