Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to extract the type of an unnamed struct to create a new type within the struct itself?

Tags:

c++

c++11

struct

It's easy to create a method/function parametrized on the type of an unnamed struct. It is also easy to get the type after the struct's definition.

struct Foo {
  template <typename T> Foo(T*) { /* we have access to T here */ }
}
template <typename T> void baz(T*) { /* we have access to T here */ }

template<typename T> struct Bar {
  /* we have access to T here */
};

void test() {
  struct {
    Foo foo { this }; // access in a constructor
    void test() { baz(this); } // access in a function
  } unnamed;
  Bar<decltype(unnamed)> bar; // access after definition
}

But is there any "magic" that could allow the use of unnamed's type at the struct scope, or in a static method - not merely within its constructor/instance method or after an instance is declared? It's trivial when the struct is named:

// How to make it work with S absent (an unnamed struct) ?
struct S {
  Bar<S> foo; // how to get our type in an unnamed struct?
  static void wrapper(void * instance) {
    static_cast<S*>(instance)->method(); // how to get our type in an unnamed struct?
  }
  void method() { ... }
} would_be_unnamed;

This question was motivated by a question about how to implement a destructor in an unnamed struct. The trivial solution there was to wrap a named struct in an unnamed one - such wrapper can then be used in macros without clashing with any other types, etc.

struct { struct S { ... } s; } unnamed;

Solving the type access conundrum would allow a different solution to the motivating question.

like image 387
Kuba hasn't forgotten Monica Avatar asked Aug 26 '15 21:08

Kuba hasn't forgotten Monica


1 Answers

Something like this, maybe?

The idea is that you actually have two unnamed structs. Firstly, unnamed contains all the actual code/data and stuff. Then there is unnamedWrapper that, being able to use decltype over unnamed, is just a completely-forwarding (even for constructors!) wrapper around unnamed, with the single speciality that it exports unnamed's type through a typedef.

#include <cstddef>

template<typename T>
size_t templatedSizeof() {
    return sizeof(T);
}

struct {
    char    something;
    short   somethingElse;
    int     moreGargabe;
    long    evenMoreUselessGarbage;
} unnamed;

struct : public decltype(unnamed) {
    typedef decltype(unnamed)   TheType;

    using TheType::TheType; // Use same constructors
} unnamedWrapper;
like image 155
3442 Avatar answered Nov 19 '22 03:11

3442