Determining which overload was selected

后端 未结 2 1903
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-16 16:02

Let\'s say I have some arbitrary complicated overloaded function:

template  void foo(T&& );
template  void foo(T* );
vo         


        
相关标签:
2条回答
  • 2020-12-16 16:20

    I'm probably far from what you have in mind, but I've spent my time on that and it's worth to add an answer (maybe a completely wrong one, indeed):

    #include<type_traits>
    #include<utility>
    
    template <class T> void foo(T&&);
    template <class T> void foo(T*);
    void foo(int);
    
    template<int N>
    struct choice: choice<N+1> { };
    
    template<>
    struct choice<3> { };
    
    struct find {
        template<typename A>
        static constexpr
        auto which(A &&a) {
            return which(choice<0>{}, std::forward<A>(a));
        }
    
    private:
        template<typename A>
        static constexpr
        auto which(choice<2>, A &&) {
            // do whatever you want
            // here you know what's the invoked function
            // it's template<typename T> void foo(T &&)
            // I'm returning its type to static_assert it
            return &static_cast<void(&)(A&&)>(foo);
        }
    
        template<typename A>
        static constexpr
        auto which(choice<1>, A *) {
            // do whatever you want
            // here you know what's the invoked function
            // it's template<typename T> void foo(T *)
            // I'm returning its type to static_assert it
            return &static_cast<void(&)(A*)>(foo);
        }
    
        template<typename A>
        static constexpr
        auto
        which(choice<0>, A a)
        -> std::enable_if_t<not std::is_same<decltype(&static_cast<void(&)(A)>(foo)), decltype(which(choice<1>{}, std::forward<A>(a)))>::value, decltype(&static_cast<void(&)(A)>(foo))>
        {
            // do whatever you want
            // here you know what's the invoked function
            // it's void foo(int)
            // I'm returning its type to static_assert it
            return &foo;
        }
    };
    
    int main() {
        float f = .42;
        static_assert(find::which(0) == &static_cast<void(&)(int)>(foo), "!");
        static_assert(find::which("hello") == &static_cast<void(&)(const char *)>(foo), "!");
        static_assert(find::which(f) == &static_cast<void(&)(float&)>(foo), "!");
        static_assert(find::which(.42) == &static_cast<void(&)(double&&)>(foo), "!");
    }
    

    I'll delete this answer after a short period during the which I expect experts to curse me. :-)

    0 讨论(0)
  • 2020-12-16 16:23

    Barry, sorry for the misunderstanding in my first answer. In the beginning I understood your question in a wrong way. 'T.C.' is right, that it is not possible except in some rare cases when your functions have different result types depending on the given arguments. In such cases you can even get the pointers of the functions.

    #include <string>
    #include <vector>
    #include <iostream>
    
    //template <class T> T foo(T ) { std::cout << "template" << std::endl; return {}; };
    std::string foo(std::string) { std::cout << "string" << std::endl; return {}; };
    std::vector<int> foo(std::vector<int>) { std::cout << "vector<int>" << std::endl; return {}; };
    char foo(char) { std::cout << "char" << std::endl; return {}; };
    
    template<typename T>
    struct Temp
    {
        using type = T (*) (T);
    };
    
    #define GET_OVERLOAD(func,param) static_cast<Temp<decltype(foo(param))>::type>(func);
    
    int main(void)
    {
        auto fPtr1 = GET_OVERLOAD(foo, 0);
        fPtr1({});
    
        auto fPtr2 = GET_OVERLOAD(foo, std::string{"hello"});
        fPtr2({});
    
        auto fPtr3 = GET_OVERLOAD(foo, std::initializer_list<char>{});
        fPtr3({});
    
        auto fPtr4 = GET_OVERLOAD(foo, std::vector<int>{});
        fPtr4({});
    
        auto fPtr5 = GET_OVERLOAD(foo, std::initializer_list<int>{});
        fPtr5({});
    
        return 0;
    }
    

    The output is:

    char
    string
    string
    vector<int>
    vector<int>
    
    0 讨论(0)
提交回复
热议问题