2

By the C++ standard n3376, the following code is ill-formed.

using cell = pair<void*, cell*>; // ill-formed

Is there any way to implement cell, which is an reasonable data structure, without defining an new cell class in C++?

SU3
  • 5,064
  • 3
  • 35
  • 66
ZijingWu
  • 3,350
  • 3
  • 25
  • 40

3 Answers3

2

At the cost of (quite some) readability, you may use a custom pair and some specialization to achieve something similar

struct self {};

template<typename F, typename S>
struct pair
{
    F first;
    S second;

    // ...
};

template<typename F>
struct pair<F, self*> : pair<F, pair*>
{
};

And you write

using cell = pair<void*, self*>;
Passer By
  • 19,325
  • 6
  • 49
  • 96
1

As far as I know, your only option is inheritance, i.e.

struct cell : std::pair<void*,cell*> { };

If you need cell to be of the same type as std::pair<void*,cell*>, you could cast the former to the latter at the point where that matters.

SU3
  • 5,064
  • 3
  • 35
  • 66
  • The OP doesn't want to define cell as a class. Also, I don't think you are allowed to derive from `std::pair`. – R Sahu Mar 27 '18 at 03:53
  • I know, but I thought it'd be more productive to show him this, then to just say *no*. – SU3 Mar 27 '18 at 03:54
  • "I don't think you are allowed to derive from `std::pair`". Why? `std::pair` is not `final` in the standard. – SU3 Mar 27 '18 at 03:55
  • I can't find the section of the library that talks about being able/unable to derived from classes defined in the standard library. – R Sahu Mar 27 '18 at 04:08
  • @RSahu That's just a general guideline. The rational is that since the standard does not prescribe library implementation, one could get unexpected behavior, because member variables or functions can be overshadowed. Here, we are not adding anything new to the struct, so it's completely safe. – SU3 Mar 27 '18 at 04:17
  • @RSahu Also, there are types in the standard library that are actually meant to be inherited. Here's a discussion on SO https://stackoverflow.com/q/1073958/2640636 – SU3 Mar 27 '18 at 04:18
  • From the accepted answer of that post: "If it doesn't have any virtual methods, then you shouldn't be using it as a base." – R Sahu Mar 27 '18 at 04:19
  • Nothing ventured, nothing gained. – SU3 Mar 27 '18 at 04:26
0

Another option could be to use

using cell = pair<void*, void*>;

and then cast the second element to the right type when necessary. You could write a function for that, like

cell& get_cell(cell& x) {
  return *static_cast<cell*>(x.second);
}
SU3
  • 5,064
  • 3
  • 35
  • 66