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

后端 未结 2 455
鱼传尺愫
鱼传尺愫 2021-02-06 16:18

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

相关标签:
2条回答
  • 2021-02-06 16:55

    The following seems to work. Please tell me if it needs improvement. Live example.

    class Haser {
    public:
    template <typename T, typename = int>
    static constexpr bool HasX = false;
    
    template <typename T> 
    static constexpr bool HasX<T, decltype((void) T::x, 0)> = true;
    };
    
    struct A { 
    private:    
        int x;
        friend Haser;
    };
    

    Haser::HasX<A> is true.

    0 讨论(0)
  • 2021-02-06 17:11

    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.

    0 讨论(0)
提交回复
热议问题