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); 
} 

Сейчас мой дополнительный код lõoke так:

#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

Укажите '' ContainerOut' для Map', при вызове 'Map'. например 'Map >', другие параметры шаблона будут выведены компилятором. – mnciitbhu

+0

Или вы можете по умолчанию использовать его так же, как 'ContainerIn', с небольшим жонглированием. –

+0

@AlanStokes Даже принуждение 'ContainerOut' к тому же, что и' ContainerIn', используя только 'Container' [подобное] (http://ideone.com/IENKSe), не помогает. –

ответ

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

Compiler ошибки говорит:

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', принимая' xs' по значению, а не const ref больше не слишком расточительно, на мой взгляд. Недостаточно переключиться на вашу версию «Карта» *** или *** «Карри». Нужно делать и то, и другое. Только изменение 'Curry' [производит ошибки] (http://ideone.com/HYqYll). –