C++ (重新)命名的std::pair成员
我不想写C++ (重新)命名的std::pair成员,c++,templates,stl,typedef,traits,C++,Templates,Stl,Typedef,Traits,我不想写town->first我想写town->name。内联命名访问器(and)是迄今为止我找到的最好的解决方案。我的命名访问器问题是类型安全性丢失: pair可以引用struct{int index;double value;}或struct{int population;double avg_temp;}。有人能提出一个简单的方法,也许是类似于特征的方法吗 我经常想从函数中返回一对或一个元组,每次都要引入一个新类型,如struct city{string name;int zipcode;
town->first
我想写town->name
。内联命名访问器(and)是迄今为止我找到的最好的解决方案。我的命名访问器问题是类型安全性丢失:
pair
可以引用struct{int index;double value;}
或struct{int population;double avg_temp;}
。有人能提出一个简单的方法,也许是类似于特征的方法吗
我经常想从函数中返回一对或一个元组,每次都要引入一个新类型,如struct city{string name;int zipcode;}
及其构造函数,这是非常累人的。我很高兴了解boost和C++0x,但我需要一个没有boost的纯C++03解决方案
更新
Re Andrewski的问题:是的,像
pair
这样的(假设的)语法将创建一个与pair
不同的类型,这将满足您的要求。我甚至不介意实现一个定制的pair/tuple模板类,当我需要一个新类型时,只需适当地向它传递一个“name traits”模板参数。我不知道“名字特征”会是什么样子。也许这是不可能的。也许您可以从pair继承您自己的pair类,并在构造函数中设置两个名为name和zipcode的引用(只需确保实现您将使用的所有构造函数)我看不出您能做得比
struct city { string name; int zipcode; };
那里没有不必要的东西。您需要这两个成员的类型,您的整个问题都是围绕给这两个成员命名而提出的,并且您希望它是唯一的类型
您知道聚合初始化语法,对吗?您不需要构造函数或析构函数,编译器提供的那些都很好
例如:
类型安全性要求引入新类型,否则,
pair
在(名称、zipcode)和(填充、临时)之间不明确
在C++03中,返回新元组需要:
city retval = { "name", zipcode };
return retval;
或者编写一个方便的构造函数:
city::city( std::string newName, int newZip ) : name(newName), zipcode(newZip) {}
得到
return city("name", zipcode);
但是,使用C++0x时,您可以编写
return { "name", zipcode };
而且不需要用户定义的构造函数。我认为您真的应该在这里引入新类型。我完全支持stl拥有一个pair类,但这正是java人认为他们不想拥有pair类的原因,你应该总是为你的piar类引入新类型
stl解决方案的好处在于,您可以使用gerneric类对,但只要您确实希望以不同于第一/第二的方式命名成员,就可以引入新的类型/类。除此之外,引入新类使您可以在必要时轻松添加第三个成员。由于
std::pair
通常用于在std::map
容器中存储条目,您可能需要查看
简介:
#include <boost/bimap/bimap.hpp>
#include <string>
#include <iostream>
struct name {}; // Tag for the default 'first' member
struct zipcode {}; // Tag for the default 'second' member
int main()
{
using namespace boost::bimaps;
typedef bimap <tagged<std::string, name>, tagged<int, zipcode> > Cities;
typedef Cities::value_type registration;
Cities cities;
cities.insert(registration("Amsterdam", 20));
cities.insert(registration("Rotterdam", 10));
// ...
std::string cityName;
std::cin >> cityName;
Cities::map_by<name>::const_iterator id_iter = cities.by<name>().find(cityName);
if( id_iter != cities.by<name>().end() )
{
std::cout << "name: " << id_iter->get<name>() << std::endl
<< "zip: " << id_iter->get<zipcode>() << std::endl;
}
return 0;
}
我邀请您浏览Boost Bimap的文档,以获得完整的图片,我想您可以详细介绍一下
struct City : public std::pair<string, int> {
string& name() { return first; }
const string& name() const { return first; }
int& zip() { return second; }
int zip() const { return second; }
};
struct City:public std::pair{
string&name(){return first;}
常量字符串&name()常量{return first;}
int&zip(){return second;}
int zip()常量{return second;}
};
虽然通过
结构城市{string name;int-zipcode;}
看起来很好,但最接近您要查找的内容。虽然不完美,但可以使用标记数据:
template <typename tag_type, typename pair_type>
typename tag_type::type& get(pair_type& p);
typedef std::pair<std::string /*name*/, int /*zipcode*/> city;
struct name { typedef std::string type; };
struct zipcode { typedef int type; };
template <>
std::string& get<name, city>(city& city)
{
return city.first;
}
template <>
int& get<zipcode, city>(city& city)
{
return city.second;
}
int main()
{
city c("new york", 10001);
std::string n = get<name>(c);
int z = get<zipcode>(c);
}
您可以使用指向成员运算符的指针。有几种选择。这是最简单的方法
typedef std::map< zipcode_t, std::string > zipmap_t;
static zipcode_t const (zipmap_t::value_type::*const zipcode)
= &zipmap_t::value_type::first;
static std::string (zipmap_t::value_type::*const zipname)
= &zipmap_t::value_type::second;
// Usage
zipmap_t::value_type my_map_value;
std::string &name = my_map_value.*zipname;
typedef std::mapzipmap\t;
静态zipcode_t const(zipmap_t::value_type::*const zipcode)
=&zipmap\u t::value\u type::first;
静态标准::字符串(zipmap\u t::value\u类型::*常量zipname)
=&zipmap\u t::value\u type::second;
//用法
zipmap_t::value_键入my_map_值;
std::string&name=my_map_值。*zipname;
您可以将一个伪类型的访问器放入一个专用的
名称空间
,以将它们与其他内容分开。然后它看起来像my\u map\u value.*zip::name
。但是,除非您真的需要使用对
,否则只需定义一个新的结构
可能会更容易。我提出了一个实用工具对
宏,可以这样使用:
实用工具对(ValidityDaterRange,
时间,开始日期,
时间,结束日
);
然后,无论何时需要访问ValidityDaterRange
的字段,都可以这样做:
ValidityDateRange r=gettherangefromwhere();
自动启动=r.startDay();//开始新的一天
r、 endDay()=aNewDay();//设定结束日期
r、 startDay(aNewDay1())//一次性设置开始和结束日期。
.endDay(aNewDay2());
这就是实现:
#包括
#定义实用工具对成员(配对名称、序号、类型、名称)\
const type&name()const{return ordinality;}\
type&name(){return ordinality;}\
pairName&name(const type&m){ordinality=m;return*this;}\
/***/
#定义实用工具对(pairName、firstMemberType、firstMemberName、secondMemberType、secondMemberName)\
结构pairName:std::pair{\
实用工具\对\成员\(pairName、first、firstMemberType、firstMemberName)\
实用工具对成员(pairName、second、secondMemberType、secondMemberName)\
} \
/***/
可能不值得额外的内存,但如果您想保留std::pair
或std::tuple
/的优势,保持与不可更改API的兼容性,您可以从它们继承,然后定义对其成员的引用
除了
namespace city
{
typedef std::pair<std::string /*name*/, int /*zipcode*/> type;
std::string& name(type& city)
{
return city.first;
}
int& zipcode(type& city)
{
return city.second;
}
}
int main()
{
city::type c("new york", 10001);
std::string n = city::name(c);
int z = city::zipcode(c);
}
typedef std::map< zipcode_t, std::string > zipmap_t;
static zipcode_t const (zipmap_t::value_type::*const zipcode)
= &zipmap_t::value_type::first;
static std::string (zipmap_t::value_type::*const zipname)
= &zipmap_t::value_type::second;
// Usage
zipmap_t::value_type my_map_value;
std::string &name = my_map_value.*zipname;
#include <tuple>
struct PairShadow : public std::pair<int, double> {
using std::pair<int, double>::pair;
PairShadow & operator=(PairShadow const &) { /*call parent op here*/ }
int & x = this->first;
double & y = this->second;
};
struct TupleShadow: public std::tuple<int, double> {
using std::tuple<int, double>::tuple;
PairShadow & operator=(PairShadow const &) { /*call parent op here*/ }
int & x = std::get<0>(*this);
double & y = std::get<1>(*this);
};
auto main() -> int {
auto twinShadow = PairShadow(1,3.0);
auto tupleShadow = TupleShadow(1,3.0);
return tupleShadow.y;
}