How to detect whether there is a specific PRIVATE member variable in class?

c++, constexpr, friend, template-meta-programming

Solution

Well... not sure about correctness and limits of this solution... but...

If you define an helper struct with an `x` element accessible

struct check_x_helper
 { int x; };

you can write a template struct that inherit from both `check_x_helper` and the class you want to see if contain a `x` member

template <typename T>
struct check_x : public T, check_x_helper

Inside `check_x` you can declare (declare only: are used inside a `decltype()`) as follows

template <typename U = check_x, typename = decltype(U::x)>
static constexpr std::false_type check (int);

static constexpr std::true_type check (long);

Observe the first one, the template one: when the checked class (`T`) contains an `x` member, the `decltype(U::x)` is ambiguous because `x` is inherited from both `T` and `check_x_helper`, so this function is SFINAE discarded.

On contrary, when `T` doesn't contains an `x` member, there isn't an ambiguity, the `decltype(U::x)` is the type of `check_x_helper::x` (`int`) and the first `check()` function remain enabled.

Now you need something as

using type = decltype(check(0));

static constexpr auto value = type::value;

to call `check(0)` (the `int` parameter express the preference to the template version) and save the detected `value` in a `static constexpr` variable.

The following is a full compiling example

#include <iostream>
#include <utility>

class foo
 { int x; };

struct bar
 { };

struct check_x_helper
 { int x; };

template <typename T>
struct check_x : public T, check_x_helper
 {
   template <typename U = check_x, typename = decltype(U::x)>
   static constexpr std::false_type check (int);

   static constexpr std::true_type check (long);

   using type = decltype(check(0));

   static constexpr auto value = type::value;
 };

int main()
 {
   std::cout << check_x<foo>::value << std::endl;
   std::cout << check_x<bar>::value << std::endl;
 }

Drawback of this solution: `decltype(U::x)` fail (ambiguity) also when `T` declare `x` as a method or as a `using` type. So given

class foo
 { int x () { return 0;} ; };

or

class foo
 { using x = int; };

from `check_x<foo>::value` you obtain `1`.

Problem

This question is based on this post. Goal: I would like to know if a class has the member variable `x`. I would like to receive `true` regardless whether or not this variable is `private`, `public` or `protected`. Approach: You can get the information if a class has a member variable using the following code: ``` template <typename T, typename = int> struct HasX : std::false_type { }; template <typename T> struct HasX <T, decltype((void) T::x, 0)> : std::true_type { }; ``` Use it with ``` if constexpr (HasX<my_class>::value) { // do stuff with x } else { // ... } ``` The above code does not work in this case ``` struct my_class { private: int x; }; ``` How can I make this work? I would like `HasX<my_class>::value` to be `true`. Ideas: Use a `friend` class which has access to `T::x`. This does not seem to work. Check out this live example.

Original source

Related problems