Member function call in decltype

前端 未结 6 1063
北荒
北荒 2021-02-05 09:23

The following code:

struct A
{
    int f(int);
    auto g(int x) -> decltype(f(x));
};

Fails to compile with the error:

erro         


        
相关标签:
6条回答
  • 2021-02-05 09:37

    Comeau doesn't like auto as a top level return type, but the following compiles successfully:

    template <typename R, typename C, typename A1> R get_return_type(R (C::*)(A1));
    
    struct A
    {
        int f(int);
        decltype(get_return_type(&A::f)) g(int x);
    };
    

    Basically, you have to declare at least one additional construct that gets you the type you want. And use decltype directly.

    EDIT: Incidentally, this works fine for diving into the return type of a member function as well:

    template <typename R, typename C, typename A1> R get_return_type(R (C::*)(A1));
    
    struct B { int f(int); };
    
    struct A
    {
        int f(int);
        B h(int);
    
        decltype(get_return_type(&A::f)) g(int x);
    
        decltype(get_return_type(&A::h).f(0)) k(int x);
    };
    
    int main()
    {
        return A().k(0);
    }
    

    Granted, it doesn't have the same convenience of auto f()-> ..., but at least it compiles.

    0 讨论(0)
  • 2021-02-05 09:41

    Here are the magic words:

    struct A
    {
        int f(int);
        auto g(int x) -> decltype((((A*)0) ->* &A::f)(x)) ;
    };
    

    Edit I see from Mikael Persson's answer that this is how it's done in boost.

    0 讨论(0)
  • 2021-02-05 09:42

    Seems to me that does not work because the decltype is outside of the method and A is at that moment an incomplete type (so you can't even do A().f(x)).

    But you should not really need that. Outside of the declaration of A this will work as expected, in A you should know the return type of the function that you declared a few lines above. Or you could just write:

    struct A {
        typedef int ret_type;
        ret_type f(int x);
        ret_type g(int x);
    };
    

    This even works with plain c++03.

    0 讨论(0)
  • 2021-02-05 09:43

    After some tests, neither decltype(declval<A>().f(x)) nor decltype(((A*)0)->f(x)) will work.

    However, it seems that using boost::bind will work (and it's "under-the-hood" version):

    struct A
    {
        int f(int);
        auto g(int x) -> decltype(boost::bind(&A::f,0,x)());
        auto h(int x) -> decltype((((A*)0)->*(&A::f))(x)); //similarly (what Boost.Bind does under-the-hood.
    };
    

    Of course, this is not pretty. I guess you can look into how boost::bind does it to maybe find a nicer solution.

    EDIT

    As MSN suggested, you can also make your own function template to resolve this:

    template< typename R, typename C, typename... Args > R member_func(R (C::*)(Args...)); 
    
    struct A
    {
        int f(int);
        auto g(int x) -> decltype(member_func(&A::f));
    };
    
    0 讨论(0)
  • 2021-02-05 09:44

    Currently you can only access 'this' and members of the class inside the function body, but this is likely to be changed soon:

    http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1207

    0 讨论(0)
  • 2021-02-05 09:45

    result_of and decltype in combination can give the the return type for a member function

    #include <type_traits>
    using namespace std;
    
    struct A
    {
        int f(int i) { return i; } 
        auto g(int x) -> std::result_of<decltype(&A::f)(A, int)>::type
        { 
            return x;
        }
    };
    
    
    int main() {
        A a;
    static_assert(std::is_same<decltype(a.f(123)), 
                      decltype(a.g(123))>::value, 
                      "should be identical");
    return 0;
    }
    
    0 讨论(0)
提交回复
热议问题