Я пытаюсь получить следующую основную функцию для компиляции и работы, как ожидалось:
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);
}
Прямо сейчас мой дополнительный код выглядит следующим образом:
#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... ); };
}
и это не компилируется.
Любая идея, как можно заставить компилятор выводить параметры шаблона?
Ошибка компилятора говорит:
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
Одно возможное решение, чтобы избежать необходимости использовать 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