vendredi 26 août 2016

syntax regarding static const-pointer to data member

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.

Aucun commentaire:

Enregistrer un commentaire