Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

decltype(*this) equivalent outside function body

Is it possible to write a trait, which results the type of the class it is used in? How to implement get_class in the example below?

class Foo {
    typedef get_class::type type; // type = Foo now
}; 

Note: I have to write a macro, which expands in the class body, used for multiple classes, so I cannot simply write 'typedef Foo type;'

Use case:

I have a reflectable(...) macro which generates infrastructure to iterate over members, visit them and look them up using their names:

class Foo 
{
    friend std::ostream &operator<<(std::ostream &, const Foo&);
    reflectable(
         (int) bar,
         (double) baz
    )
}

reflectable(...) should be a macro so I can get the types and member names separately as strings to build maps for the lookup.

I would like all reflectable class to be streamable, but if I put my reflectable() macro to private section, I have to add the friend declaration to the class. I would like to move it to the macro as:

friend std::ostream &operator<<(std::ostream &, const get_class::type&);
like image 850
simon Avatar asked Jun 19 '17 10:06

simon


Video Answer


1 Answers

I'm sorry, but I'm pretty sure that in standard C++ there is no way around you having to pass in the class name to the macro one way or another. For some failed attempts, see the end of this answer.


That said, I think your best bet is to slightly change your design. Instead of

friend std::ostream &operator<<(std::ostream &, const get_class::type&);

provide a public member function

void stream_to (std::ostream &) const {
  // Implementation
}

together with a free function template

template<typename T, typename std:: enable_if<has_stream_to<T>::value>::type * = nullptr>
std::ostream &operator<<(std::ostream & s, T const & t) {
  t.stream_to(s);
  return s;
}

in your libraries/programs namespace. (Note: I'll add the trait has_stream_to later, for the impatient search for "detect member function" within C++ tag)


Approaches that don't work:

  • Use a pointer to member function, extract the class type with a template function. Reason: &foo inside of a class with a member function foo won't give a member function pointer to foo. The syntax is required (by the standard) to be &C::foo (where C is the class name...).

  • Use a pointer to data member, extract the class type with a template function. Same reason as above.

  • Use a dedicated member function that returns *this, deduce the return type to get the class type. Reason: Need an instance to call this function on.

  • Use a pointer to a static member function. Reason: Such pointers are same as pointers to free functions, the class name cannot be deduced from them.

  • Use the this pointer in a member initialisation. Reason: type of member needs to encode class type somehow, but auto is not allowed for non static data members.

like image 123
Daniel Jour Avatar answered Sep 21 '22 06:09

Daniel Jour