Metaprogramming trick for sorting private functions

This is a question regarding compile-time introspection in C ++

Is there a known trick to discover that the matching function is actually private and therefore cannot be called? My intuition is that this is not possible, but maybe I'm wrong?


Explanation: using metaprogramming methods (mainly based on the SFINAE mechanism), one can detect the presence of properties (nested types, members, functions with a certain signature) in the type specified as a template parameter (i.e., we know this type exists, but we don’t we don’t know about this type). Based on such introspection predicates, one can create specialized implementations, adapters, etc.

Now the concrete twist is that such a predicate can correspond to a private member of the class. When we subsequently generate code based on the result of this (false) match, compilation fails because we are not actually allowed to access this member. So it would be nice to handle such false matches ...

+4
source share
1 answer

Ok, I never use it. This is just an idea.

So, to determine if a function exists , we need something like this:

#include <iostream>

#define DEFINE_METHOD_CHECKER(RETURN_TYPE, METHOD_NAME, PARAMETERS)     \
template<typename T>                                                    \
struct Is ## METHOD_NAME ## MemberFunctionExists                        \
{                                                                       \
private:                                                                \
    typedef char True;                                                  \
    typedef char (&False)[2];                                           \
    template<typename U, RETURN_TYPE (U::*)PARAMETERS = &U::METHOD_NAME>\
    struct Checker                                                      \
    {                                                                   \
        typedef True Type;                                              \
    };                                                                  \
    template<typename U>                                                \
    static typename Checker<U>::Type Tester(const U*);                  \
    static False Tester(...);                                           \
public:                                                                 \
    enum { value = (sizeof(Tester(static_cast<const T*>(0))) == sizeof(True)) }; \
}

// IsMethodMemberFunctionExists<T>::value
DEFINE_METHOD_CHECKER(int, Method, (bool));
// IsTestMemberFunctionExists<T>::value
DEFINE_METHOD_CHECKER(int*, Test, (int&, char));

class Exists
{
public:
    int Method(bool);
    int* Test(int&, char);
};

class NotExists
{
};

int main()
{
   std::cout << IsMethodMemberFunctionExists<Exists>::value << std::endl;
    std::cout << IsTestMemberFunctionExists<Exists>::value << std::endl;

    std::cout << IsMethodMemberFunctionExists<NotExists>::value << std::endl;
    std::cout << IsTestMemberFunctionExists<NotExists>::value << std::endl;
}


Output:
1
1
0
0

Live

. public: - , 0 - - ( " ++ 11", @TC):

class Exists
{
//public:
    int Method(bool);
    int* Test(int&, char);
};

Output:
0
0
0
0

Live

, , , , . :

struct ITest
{
    virtual void foo() = 0;
};

class Test : ITest
{
    // foo() is private AND it override Itest::foo() !
    void foo();
}

// std::is_abstract<Test>() yields false !

,

#define DEFINE_PRIVATE_METHOD_CHECKER(RETURN_TYPE, METHOD_NAME, PARAMETERS) \
DEFINE_METHOD_CHECKER(RETURN_TYPE, METHOD_NAME, PARAMETERS); \
template<typename T> \
struct IsPrivate ## METHOD_NAME ## MemberFunctionExists \
{ \
public: \
    struct IOverrideTest \
    { \
        virtual RETURN_TYPE METHOD_NAME PARAMETERS = 0; \
    }; \
    \
    class OverrideTest : T, IOverrideTest {}; \
    \
public: \
    enum { value = !IsMethodMemberFunctionExists<T>::value && !std::is_abstract<OverrideTest>::value }; \
}

// IsPrivateMethodMemberFunctionExists<T>::value
DEFINE_PRIVATE_METHOD_CHECKER(int, Method, (bool));

#include <iostream>

class PrivateExists
{
private:
    int Method(bool);
    int* Test(int&, char);
};

class NotExists
{
};

int main()
{   
    std::cout << IsPrivateMethodMemberFunctionExists<PrivateExists>::value << std::endl;
    std::cout << IsMethodMemberFunctionExists<PrivateExists>::value << std::endl;

    //std::cout << IsPrivateMethodMemberFunctionExists<NotExists>::value << std::endl;
    //std::cout << IsMethodMemberFunctionExists<NotExists>::value << std::endl;
}

, :

Clang Live :

1
0

gcc Live:

0
0

V++ Live .

.. , :

int main()
{   
    std::cout << IsPrivateMethodMemberFunctionExists<PrivateExists>::value << std::endl;
    std::cout << IsMethodMemberFunctionExists<PrivateExists>::value << std::endl;

    std::cout << IsPrivateMethodMemberFunctionExists<NotExists>::value << std::endl;
    std::cout << IsMethodMemberFunctionExists<NotExists>::value << std::endl;
}

Clang Live:

1
0
1
0

gcc Live

0
0
0
0

: :

class Exists
{
    void foo();
};

struct ITest
{
    virtual void foo() = 0;
};

class TestExists : Exists, ITest
{
};

TestExists foo(), . . Bu ...

+5

All Articles