Extracting the return type from an overloaded function

后端 未结 3 2060
臣服心动
臣服心动 2020-12-10 14:39

I want to extract the return type of a function. Problem is, there are other functions with the same name but different signature, and I can not get C++ to select the approp

相关标签:
3条回答
  • 2020-12-10 15:02

    It's very hard to inspect an overloaded function name without arguments. You can inspect the return types for overloads that differ in arity -- provided that no arity has more than one overload. Even then, turning a hard error (if/when a given arity does have more than one overload) into SFINAE is a pain as it requires writing a trait just for that particular function(!) since overloaded function names can't be passed as any kind of argument. Might as well require user code to use an explicit specialization...

    template<typename R>
    R
    inspect_nullary(R (*)());
    
    template<typename R, typename A0>
    R
    inspect_unary(R (*)(A0));
    
    int f();
    void f(int);
    
    int g();
    double g();
    
    typedef decltype(inspect_nullary(f)) nullary_return_type;
    typedef decltype(inspect_unary(f)) unary_return_type;
    
    static_assert( std::is_same<nullary_return_type, int>::value, "" );
    static_assert( std::is_same<unary_return_type, void>::value, "" );
    
    // hard error: ambiguously overloaded name
    // typedef decltype(inspect_nullary(g)) oops;
    

    Given that you're using C++0x, I feel the need to point out that there is (IMO) never a need to inspect a return type beyond typename std::result_of<Functor(Args...)>::type, and that doesn't apply to function names; but perhaps your interest in this is purely academical.

    0 讨论(0)
  • 2020-12-10 15:14

    I think that this can be done with decltype and declval:

    For example: decltype(f(std::declval<T>())).

    0 讨论(0)
  • 2020-12-10 15:19

    Okay, after a few attempts I managed to work around the std::declval method suggested by Mankarse. I used a variadic class template to fixate the parameters, and used the template deduction of functions to get the return value from a function pointer. Its current syntax is typeof(ResultOf<parameters>::get(function)), unfortunately it is still far from the desired resultof<parameters>(function) form. Will edit this answer if I find a way to further simplify it.

    #include <iostream>
    #include <typeinfo>
    
    using namespace std;
    
    template <class... Args>
    class ResultOf
    {
        public:
            template <class R>
            static R get (R (*) (Args...));
            template <class R, class C>
            static R get (R (C::*) (Args...));
    };
    
    class NoDefaultConstructor
    {
        public:
            NoDefaultConstructor (int) {}
    };
    
    int f ();
    double f (int x);
    bool f (NoDefaultConstructor);
    int f (int x, int y);
    
    
    int main (int argc, char* argv[])
    {
        if(argc||argv){}
    
        cout << typeid(typeof(ResultOf<>::get(f))).name() << endl;
        cout << typeid(typeof(ResultOf<int>::get(f))).name() << endl;
        cout << typeid(typeof(ResultOf<NoDefaultConstructor>::get(f))).name() << endl;
        cout << typeid(typeof(ResultOf<int, int>::get(f))).name() << endl;
    
        typeof(ResultOf<int>::get(f)) d = 1.1;
        cout << d << endl;
    }
    

    Edit:

    Managed to solve it with variadic macros, the syntax is now resultof(f, param1, param2, etc). Without them I couldn't pass the commas between the parameter types to the template. Tried with the syntax resultof(f, (param1, param2, etc)) to no avail.

    #include <iostream>
    
    using namespace std;
    
    template <class... Args>
    class Param
    {
        public:
            template <class R>
            static R Func (R (*) (Args...));
            template <class R, class C>
            static R Func (R (C::*) (Args...));
    };
    
    #define resultof(f, ...) typeof(Param<__VA_ARGS__>::Func(f))
    
    int f ();
    double f (int x);
    int f (int x, int y);
    
    int main (int argc, char* argv[])
    {
        resultof(f, int) d = 1.1;
        cout << d << endl;
    }
    
    0 讨论(0)
提交回复
热议问题