Is there any way to detect whether a function exists and can be used at compile time?

后端 未结 1 543
没有蜡笔的小新
没有蜡笔的小新 2021-01-05 08:16

Edit: The short answer to my question is that I had a mistaken view of what SFINAE can do and it does not check the function body at all: does sfinae instan

相关标签:
1条回答
  • 2021-01-05 08:42

    I don't have the time to check this now, but you can add an specialization of Final: template <typename T> struct Final< Inner<T> >; (which also helps ensure that the type is always a Inner. With that you can extract the type used to instantiate Inter.

    Now the second problem is how to use SFINAE to detect whether a member function exists. I believe this should not be too complex (if you don't need to make this generic):

    // Find out whether U has `void f()` member
    template <typename U>
    struct has_member_f {
        typedef char yes;
        struct no { char _[2]; };
        template<typename T, void (T::*)() = &T::f>
        static yes impl( T* );
        static no  impl(...);
    
        enum { value = sizeof( impl( static_cast<U*>(0) ) ) == sizeof(yes) };
    };
    

    You might be able to extend this a bit to make it a bit more generic, but the name of the function I don't think you can make generic. Of course, you could write that as a macro that generates has_member_##arg and uses &T:: arg. The type of the member is probably easier to generalize...

    Alternatively, since I don't think this can be made generic, you can use the trick inside has_member directly in your type: provide two callFuncA overloads, one templated with the optional second argument with the signature that you want and defaulted to &T::FuncA that forwards the call, the other with ellipsis that is a noop. Then callFuncs would call callFuncA and callFuncB, and SFINAE will dispatch to either the forwarder or the noon and you get your desired behavior.

    template<typename T>
    struct Final< Inter<T> >
    {
        template <typename U, void (U::*)() = &U::FuncA>
        void callFuncA( Inter<T>* x ) {
            x.FuncA();
        }
        void callFuncA(...) {}
    
        void CallFuncs() {
            callFuncA(&t);                 // Cannot pass nonPOD types through ...
            // Similarly TryCallFuncB(t);
        }
        Inter<T> t;
    };
    
    0 讨论(0)
提交回复
热议问题