How to deduce the return type of a function object from parameters list?

后端 未结 2 1064
说谎
说谎 2021-02-02 10:13

I\'m trying to write a projection function that could transform a vector into a vector. Here is an example:

auto v =          


        
2条回答
  •  广开言路
    2021-02-02 11:04

    Option #1:

    Basic decltype() usage:

    template 
    auto select(const std::vector& c, F f)
        -> std::vector
    {
        using R = decltype(f(c[0]));
        std::vector v;
        std::transform(std::begin(c), std::end(c), std::back_inserter(v), f);
        return v;
    }
    

    Option #2:

    Basic std::result_of usage:

    template ::type>
    std::vector select(const std::vector& c, F f)
    {
        std::vector v;
        std::transform(std::begin(c), std::end(c), std::back_inserter(v), f);
        return v;
    }
    

    Option #3:

    Advanced decltype() usage and perfect-forwarding (see notes*):

    template 
    auto select(const std::vector& c, F&& f)
        -> std::vector::type&>()(*c.begin()))>::type>
    {
        using R = typename std::decay::type&>()(*c.begin()))>::type;
        std::vector v;
        std::transform(std::begin(c), std::end(c)
                     , std::back_inserter(v)
                     , std::forward(f));
        return v;
    }
    

    Option #4:

    Advanced std::result_of usage and perfect-forwarding (see notes*):

    template ::type&(typename std::vector::const_reference)>::type>::type>
    std::vector select(const std::vector& c, F&& f)
    {
        std::vector v;
        std::transform(std::begin(c), std::end(c)
                     , std::back_inserter(v)
                     , std::forward(f));
        return v;
    }
    

    * Note: Options #3 and #4 assume that the std::transform algorithm takes a function object by-value, and then uses it as a non-const lvalue. This is why one can see this strange typename std::decay::type& syntax. If the function object is supposed to be called within the select function itself, and the result type is not going to be used as a container's template argument (for the purpose of what the outer-most std::decay is used), then the correct and portable syntax for obtaining the return type is:

    /*#3*/ using R = decltype(std::forward(f)(*c.begin()));
    
    /*#4*/ typename R = typename std::result_of::const_reference)>::type
    

提交回复
热议问题