2

我试图让下面的主要功能来编译和工作像预期:函数模板,部分应用程序和模板实参推演

int main() 
{ 
    auto square = [](int x){ return x*x; }; 

    typedef std::vector<int> Row; 
    typedef std::vector<Row> Mat; 
    Mat mat; 
    auto squareElements = Curry(Map<Row>, square); 
    Mat squaredMat = Map<Mat>(squareElements, mat); 
} 

现在我补充代码looke这样的:

#include <algorithm> 
#include <functional> 
#include <iterator> 
#include <vector> 

template <typename ContainerOut, typename ContainerIn, typename F> 
ContainerOut Map(const F& f, const ContainerIn& xs) 
{ 
    ContainerOut ys; 
    // For performance reason one would use 
    // ys.reserve(xs.size()) 
    // and std::back_inserter instead of std::inserter 
    // if ys is a std::vector. 
    auto it = std::inserter(ys, end(ys)); 
    std::transform(begin(xs), end(xs), it, f); 
    return ys; 
} 

template <typename Ret, typename Arg1, typename ...Args> 
auto Curry(Ret f(Arg1, Args...), Arg1 arg) -> std::function<Ret(Args...)> 
{ 
    return [=](Args ...args) { return f(arg, args...); }; 
} 

does not compile

任何想法如何让编译器推导出模板参数?

+1

调用'Map'时指定'ContainerOut'为'Map'。例如'Map >',编译器会推导出其他模板参数。 – mnciitbhu

+0

或者你可以默认它与'ContainerIn'一样,只需要一点点杂耍。 –

+0

@AlanStokes即使仅仅使用'Container'[像这样](http://ideone.com/IENKSe)来强制'ContainerOut'与'ContainerIn'一样没有帮助。 –

回答

0

一个可能的解决方案,以避免使用std::placeholders::_1每一次std::bind

#include <algorithm> 
#include <functional> 
#include <iterator> 
#include <utility> 
#include <vector> 

template <typename Container, typename F> 
Container Map(const F& f, const Container& xs) 
{ 
    Container ys; 
    // For performance reasons one would use 
    // ys.reserve(xs.size()) 
    // and std::back_inserter instead of std::inserter 
    // if ys is a std::vector. 
    auto it = std::inserter(ys, end(ys)); 
    std::transform(begin(xs), end(xs), it, f); 
    return ys; 
} 

template <typename F, typename T> 
auto Curry(F&& f, T&& t) 
{ 
    return [f = std::forward<F>(f), t = std::forward<T>(t)] 
      (auto&&... args) 
      { return f(t, std::forward<decltype(args)>(args)...); }; 
} 

int main() 
{ 
    auto square = [](int x){ return x*x; }; 

    typedef std::vector<int> Row; 
    Row row; 
    Row squaredRow = Map(square, row); 

    typedef std::vector<Row> Mat; 
    Mat mat; 
    auto squareRow = Map<Row, decltype(square)>; 
    auto squareRowElems = Curry((Map<Row, decltype(square)>), square); 
    Mat squaredMat = Map(squareRowElems, mat); 
} 

来源:https://stackoverflow.com/a/33724222/1866775

演示:http://ideone.com/16cx0l

0

编译器错误说:

deduced conflicting types for parameter 'Arg1' ('const main()::<lambda(int)>&' and 'main()::<lambda(int)>') 
auto squareElements = Curry(Map<Row, decltype(square)>, square); 
                  ^

改变功能Curry

template <typename Ret, typename Arg1, typename... Args> 
auto Curry(Ret (*f)(const Arg1&, const Args&...), const Arg1& arg) -> std::function<Ret(Args...)> 
{ 
    return [=](Args... args) { return f(arg, args...); }; 
} 

或改变功能Map到:

template <typename Container, typename F> 
Container Map(F f, Container xs); 

这将编译!

看看我的代码:Ideone

+0

这很好,但是'Map'接受值'而不是'const'参考'xs'在我看来有点过于浪费。切换到您的'Map' ***或***'Curry'版本是不够的。一个人必须这样做。只改变'Curry' [产生错误](http://ideone.com/HYqYll)。 –