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
.
if contexpr
take advantage of knowing that info? – Kaliskimy_class::x
from a class which isfriend
ofmy_class
. – BlindwormT
. Then I do not know ifT::x
exists. – Blindwormif constexpr
insidemy_class
'sfriend
class? – KaliskiT
has a method template, this is a backdoor to access whatever privates ofT
. There are other ways to access privates, but beware. Many "solutions" you find (even here on SO) are not valid C++, they make use of some UB and are mainly based on luck – BeeryT
made your class (the one that wants to accesx
) a friend then yourHasX
can work with a modifcation, the acces has to happen in the class that is declared as friend. – BeeryA
, ie it can accessA
s privatex
but needs to know whether that exists, then perhaps making the trait a friend ofA
is the simplest. Actually thats your solution (and one of the answers) – Beery