2

Suppose there is a class with a few data members, such as this:

struct s {
  char c;
  int i;
};

If I need a const-pointer to a member, it's simple enough:

auto s::* const ptr = &s::c;

If I try to create a static member of the same type, some weird things start happening...

For instance, this segfaulted the compiler (gcc 4.9.3):

struct s {
  char c;
  int i;
  static auto s::* const static_ptr = &s::c;
};
// internal compiler error: Segmentation fault
//      static auto s::* const static_ptr = &s::c;
//                                              ^

Using it as a static member of a different class at least finishes compiling:

struct t {
  static auto s::* const static_ptr = &s::c;
};
// error: 'constexpr' needed for in-class initialization of static data member 'char s::* const t::static_ptr' of non-integral type [-fpermissive]
//      static auto s::* const static_ptr = &s::c;
//                                              ^

That last error I don't understand, isn't &s::c a constexpr?

I do have a way to make it work, eg:

// also works with `struct s` this way, `struct t` is not needed for this
struct t {
  static char s::* const static_ptr;
};
char s::* const t::static_ptr = &s::c;

But for several reasons this is undesirable:

  1. auto cannot be used except in the definition, if it is initialized outside the class then the type must be declared.
  2. Declaring the type explicitly means either repeating the type or repeating the member name (as decltype(s::c)) - more places to maintain the same name = more mistakes possible.
  3. The above is even more of a nuisance with specialized class templates, where for each specialization this would need to be done inside and outside the class.

From this I have a two part question.

1. Why isn't &s::c a constexpr? Is there a way to make it one?

2. Is there a way to specify a static member that is a fixed pointer to a member of another class, with the type automatically determined, without resorting to decltype?

I have tried this as a member of struct s and get the same error (constexpr needed):

static constexpr auto s::* const member_c () {
  return &s::c;
}

So I'm at a loss as to what the compiler's issue is with this sort of syntax, it just doesn't make sense to me why a reference to a data member (not an instance member reference) is not a constant at compile time.

Xeren Narcy
  • 875
  • 5
  • 15
  • 1
    Your `constexpr` error has the caret misplaced, making the member itself `constexpr` [works](http://coliru.stacked-crooked.com/a/ac6a67e8c5e41031) (and `&s::c` is indeed `constexpr`). – Quentin Aug 26 '16 at 07:56
  • @Quentin really... I've honestly never seen `constexpr` used for _data members_ before so it hadn't occurred to me to try this. can you please write a little more about why this needs to be done to a data member? I'm really curious now... – Xeren Narcy Aug 26 '16 at 08:00
  • Also, that example still segfaults on my compiler :| but it so happens I _don't_ need it to be in the same class so no problems there. – Xeren Narcy Aug 26 '16 at 08:03
  • OK lets say that you can initialise a static member variable to point to a non-static member of the class. The question that rises is to which member of all the created objects of that class will it point to? – 101010 Aug 26 '16 at 08:07
  • That's why I'm not making that an answer : there's more to this question, and an Internal Compiler Error should never happen, whether the code be valid or not. And `constexpr` data members are exactly what they sound like : `constexpr` variables that are inside a class :) – Quentin Aug 26 '16 at 08:08
  • @101010 I assume you're thinking about a pointer, but this is a pointer-to-member. – Quentin Aug 26 '16 at 08:08
  • @Quentin Fair enough lol, and sure enough [testing using a newer version of gcc online](http://ideone.com/5UjdnF), it does work so it's likely a compiler bug that's since been fixed. – Xeren Narcy Aug 26 '16 at 08:10
  • 1
    And [here](http://stackoverflow.com/questions/19319291/initialisation-of-static-class-member-why-constexpr)'s a Q&A about the "why" of that constexpr -- It's a bit of a "the Standard said so" one, though. – Quentin Aug 26 '16 at 08:11
  • 1
    @Quentin I see, thanks for that. Also clears up some things I've been wondering about with static member initialization in general. But yeah makes sense now, I think. I understood it as: static members have to be initialized in one translation unit unless they're an integral constant / expression where this fact won't matter (it ought to have the same value in all units and constexpr is the guarantee). – Xeren Narcy Aug 26 '16 at 08:23

0 Answers0