C++11 Type Deduction With std::function

五迷三道 提交于 2019-12-11 01:58:22

问题


Even after reading many online resources and other questions, including template argument type deduction from std::function return type with lambda and Argument type auto deduction and anonymous lambda functions, I am struggling with clearly expressing the following in c++. I would like to avoid duplicate template arguments, which seem unnecessary.

For example, container 'H' of generic type 'A' has a generic method 'M' for generic type 'B'. This expresses my intent for 'H' and method 'M':

template<typename A>
struct H
{
    explicit H(A x) : x(x) { }
    A x;

    template<typename B>
    H<B> M(std::function<H<B>(A)> g) { return g(x); }
};

My issue is calling 'M' requires duplicate template arguments for the function call and return container. For type 'float', this isn't too bad, but with other symbols this gets unmanageable very quickly.

// This works but requires the duplicate 'float'
H<int>(1).M<float>([](int x) { return H<float>(x + 3.14); });

// These would be preferred, but neither works
H<int>(1).M<float>([](int x) { return H(x + 3.14); });
H<int>(1).M([](int x) { return H<float>(x + 3.14); });

From this question, I tried a new definition of 'H' with a generic functor type 'F' instead of a generic result type:

template<typename A>
struct H2
{
    enum { IS_H2 = true };

    explicit H2(A x) : x(x) { }
    A x;

    template<typename F,
        class = typename std::enable_if<std::result_of<F(A)>::type::IS_H2>::type>
    auto M(F g) -> decltype(g(x)) { return g(x); }
};

which allows the desired syntax:

// This now is valid
H2<int>(1).M([](int x) { return H2<float>(x + 3.14); });

// And, as expected, this is not
H2<int>(1).M([](int x) { return x + 3.14; });

But I find 'H2' almost offensive, there has to be a better way.

How can either the generic return type of a functor be restricted more cleanly or std::function be made to work with type inference? Or am I attacking the problem from the wrong angle entirely?


回答1:


That is how function template works, and there are no ways around.

Automatic template parameter deduction is done if you have a parameter in the function parameter, which is here not the case. For example, the compiler can deduce type in this function :

template<typename B>
H<B> M(std::function<H<B>(A)> g, const B&) { return g(x); }

but then you would have to pass some dummy value, which is (I think) not what you want.


Here is the example, which can not convert lambda into std::function, because template parameter deduction fails :

#include <functional>

template<typename A>
struct H
{
    explicit H(A x) : x(x) { }
    A x;

    template<typename B>
    H<B> M(std::function<H<B>(A)> g, const B&) { return g(x); }
};

int main()
{
    H<int> h(1);

    std::function<H<float>(int)> g( [](int x){ return H<float>(x + 3.14); } );
    const auto v = h.M( g, 5.5f );

    (void)v;
}


来源:https://stackoverflow.com/questions/17183761/c11-type-deduction-with-stdfunction

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!