Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ (重新)命名的std::pair成员_C++_Templates_Stl_Typedef_Traits - Fatal编程技术网

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