简体   繁体   English

指向嵌套结构中成员变量的指针

[英]pointer to member variable in nested struct

For the below class, how do I represent the pointer to the member variable qux of one of the instances of Bar ? 对于下面的类,我如何表示指向Bar实例之一的成员变量qux的指针?

struct Foo {
  struct Bar {
    int qux;
  } bar1, bar2;
};

This is needed when I use the boost::multi_index container and need to use qux as the key, which is needed in the key extractor 当我使用boost::multi_index容器并且需要使用qux作为密钥时,这是必需的,这在密钥提取器中是必需的

template<class Class,typename Type,Type Class::*PtrToMember>
struct boost::multi_index::member

I am assuming the intention is to create a boost multi_index container of Foo s and use qux as the key. 我假设的目的是创建一个Foo的boost multi_index容器,并使用qux作为键。 Though qux isn't a member of Foo , you can achieve this by indexing on the member Foo::bar1 and providing a custom comparison predicate for the ordered index. 尽管qux不是Foo的成员,但您可以通过在成员Foo::bar1上建立索引并为有序索引提供自定义比较谓词来实现此目的。 For example, if you are trying to create an ordered_unique key, you would write it like this: 例如,如果您尝试创建ordered_unique键,则可以这样编写:

ordered_unique<member<Foo, Foo::Bar, &Foo::bar1>, compare_foo_bar>

where compare_foo_bar is a friend of Foo::Bar and is defined as need: 其中compare_foo_barFoo::Bar的朋友,并根据需要进行定义:

struct compare_foo_bar
{
bool operator()(const Foo::Bar& lhs, const Foo::Bar& rhs)
{
  return lhs.qux < rhs.qux;
}
};

In your case you have Class = Foo::Bar , Type = int and PtrToMember = &Foo::Bar::qux , so this should work 在您的情况下,您具有Class = Foo::BarType = intPtrToMember = &Foo::Bar::qux ,因此这应该可行

boost::multi_index::member<Foo::Bar, int, &Foo::Bar::qux>

Based on your comment below, I modified the basic example from the Boost.MultiIndex tutorial to match your use case. 根据您在下面的评论,我修改了Boost.MultiIndex教程中的基本示例以匹配您的用例。 The original example contains the following struct 原始示例包含以下struct

/* an employee record holds its ID, name and age */
struct employee
{
  int         id;
  std::string name;
  int         age;

  employee(int id_,std::string name_,int age_):id(id_),name(name_),age(age_){}
  // ...
};

And the multi_index container is defined as 并且multi_index容器定义为

typedef multi_index_container<
  employee,
  indexed_by<
    ordered_unique<
      tag<id>,  BOOST_MULTI_INDEX_MEMBER(employee,int,id)>,
    ordered_non_unique<
      tag<name>,BOOST_MULTI_INDEX_MEMBER(employee,std::string,name)>,
    ordered_non_unique<
      tag<age>, BOOST_MULTI_INDEX_MEMBER(employee,int,age)> >
> employee_set;

Now, let us modify employee so that employee::name is actually a member of a nested struct Bar , and say employee contains two instances of Bar . 现在,让我们修改employee以使employee::name实际上是嵌套struct Bar的成员,并说employee包含Bar两个实例。

struct employee
{
  int           id;
  struct Bar
  {
    Bar(std::string name) : name(name) {}

    std::string name;
  } bar1, bar2;
  int           age;

  // ...
};

But you can't modify this declaration 但是你不能修改这个声明

ordered_non_unique<
      tag<name>,BOOST_MULTI_INDEX_MEMBER(employee,std::string,name)>

to indicate the nested struct 's data member directly. 直接指示嵌套struct的数据成员。 Instead, you need to modify the declaration to 相反,您需要将声明修改为

ordered_non_unique<
  tag<name>,BOOST_MULTI_INDEX_MEMBER(employee,employee::Bar,bar1)>

We need a way to order the employee::Bar objects, so add a comparison operator to its definition 我们需要一种方法来订购employee::Bar对象,因此在其定义中添加一个比较运算符

struct Bar
{
  // ...
  bool operator<(Bar const& other) const { return name < other.name; }
};

With these changes, if you index into the container using the tag name , you'll be ordering it based on the bar1.name data member. 进行这些更改后,如果您使用标签name索引到容器中,则将根据bar1.name数据成员对其进行排序。

Here's a complete working example . 这是一个完整的工作示例

I also initialized bar2.name to contain the reverse sequence of characters as that contained in bar1.name , and added the option to index based on that using the tag name2 . 我还初始化bar2.name含有包含在字符为的反向序列bar1.name ,并加入基于该使用标记的选项索引name2

You can resort to user-defined key extractors : 您可以使用用户定义的密钥提取器

struct Foobar1qux
{
  typedef int result_type;

  int operator()(const Foo &x)const{return x.bar1.qux;}
};

struct Foobar2qux
{
  typedef int result_type;

  int operator()(const Foo &x)const{return x.bar2.qux;}
};

typedef multi_index_container<
  Foo,
  indexed_by<
    ordered_non_unique<Foobar1qux>,
    ordered_non_unique<Foobar2qux>
  >
> multi_t1;

A more generic approach is to cascade key extractors as shown in one of the examples of Boost.MultiIndex documentation: 一种更通用的方法是级联键提取器,如Boost.MultiIndex文档的示例之一所示:

template<class KeyExtractor1,class KeyExtractor2>
struct key_from_key
{
public:
  typedef typename KeyExtractor1::result_type result_type;

  key_from_key(
    const KeyExtractor1& key1_=KeyExtractor1(),
    const KeyExtractor2& key2_=KeyExtractor2()):
    key1(key1_),key2(key2_)
  {}

  template<typename Arg>
  result_type operator()(Arg& arg)const
  {
    return key1(key2(arg));
  }

private:
  KeyExtractor1 key1;
  KeyExtractor2 key2;
};

typedef multi_index_container<
  Foo,
  indexed_by<
    ordered_non_unique<
      key_from_key<
        member<Foo::Bar,int,&Foo::Bar::qux>,
        member<Foo,Foo::Bar,&Foo::bar1>
      >
    >,
    ordered_non_unique<
      key_from_key<
        member<Foo::Bar,int,&Foo::Bar::qux>,
        member<Foo,Foo::Bar,&Foo::bar2>
      >
    >
  >
> multi_t2;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM