2017-04-10 21 views
0

我想这样做:如何链接C++`transform`和`inner_product`调用?

vector<int> v; 
v.push_back(0); 
v.push_back(1); 

v 
    .transform([](auto i) { return i + 2; }) 
    .transform([](auto i) { return i * 3; }) 
    .inner_product(0); 

换句话说,只是含蓄地用begin()end()firstlast迭代器和链的结果。

有什么(如一些图书馆),这将允许这?

+1

如果它在任何地方,它会在[Boost :: range](http://www.boost.org/doc/libs/1_63_0/libs/range/doc/html/index.html) –

+1

也,inner_product有两个范围:http://en.cppreference.com/w/cpp/algorithm/inner_product –

+0

@MooingDuck,'boost :: algorithm :: join'就是我真正想要做的。 –

回答

0

只需编写自己的课程以增加std::vector

#include <algorithm> 
#include <iostream> 
#include <numeric> 
#include <vector> 
#include <utility> 

template < typename T > 
class augmented_vector 
{ 
    std::vector <T> m_vec; 
public: 
    augmented_vector() : m_vec() {} 
    explicit augmented_vector(std::vector<T> const& in) : m_vec(in) {} 

    void push_back (T&& value) 
    { 
    m_vec.push_back(std::forward<T>(value)); 
    } 

    template < typename F > 
    augmented_vector <T> transform(F const& f) 
    { 
    std::vector <T> new_vec(m_vec.size()); 
    std::transform(m_vec.begin(), m_vec.end(), new_vec.begin(), f); 
    return augmented_vector <T> (new_vec); 
    } 

    T inner_product(T value) 
    { 
    return std::inner_product(m_vec.begin(), m_vec.end(), m_vec.begin(), value); 
    } 
}; 

int main() 
{ 
    augmented_vector<int> v; 
    v.push_back(0); 
    v.push_back(1); 

    auto val = v 
    .transform([](auto i) { return i + 2; }) 
    .transform([](auto i) { return i * 3; }) 
    .inner_product(0); 

    std::cout << val << '\n'; 
} 

或使用D programming language。它有universal function call syntax

import std.algorithm : fold, map; 
import std.stdio : writeln; 

void main() 
{ 
    auto v = [0, 1]; 
    auto x = v 
     .map!(a => a+2) 
     .map!(a => a*3) 
     .fold!((a,b) => a + b^^2)(0); 
    writeln(x); 
} 
+0

'转换'成员函数使*整个向量的*两个副本! –

+0

@DanielJour你确定吗?我认为它只产生一个副本('new_vec'),但它也可以被实现来改变'augmented_vector'的状态。然而,这是人们通常不期待的,这就是为什么我这样实施它。 –

+0

是的,'new_vec'以及返回的'augmented_vector'的成员'm_vec'。 –

0

裹的功能,提供在包装功能的样板:

template<typename Container, typename Transform> 
void transform_container(Container & container, Transform transform) { 
    std::transform(std::begin(container), std::end(container), 
       std::begin(container), /* requires output iterator */ 
       transform); 
} 

template<typename T, typename Container> 
auto inner_product_self(Container&& container, T initial) { 
    return std::inner_product(std::begin(container), std::end(container), 
          std::begin(container), 
          initial); 
} 

您的代码就变成了:

int main() { 
    std::vector<int> v(2); 
    std::itoa(std::begin(v), std::end(v), 0); 

    transform_container(v, [](auto i) { return i + 2; }); 
    transform_container(v, [](auto i) { return i * 3; }); 

    auto result = inner_product_self(container, 0); 

    std::cout << "result: " << result; 
} 

(Live on ideone)

你不拴面向对象编程!

+0

这仍然没有链接电话。如果容器的类型不相同,或者容器本身需要“const”,则链接调用非常重要。 –

+0

@NoelYap最后两个陈述都不是真的。如果容器是'const'或者如果你想为结果有不同的容器,那么你当然不能(如我的代码那样)修改容器本身。你可以很容易地做的是编写一个包装函数,它使用并返回一个不同的容器(可能是不同的类型)。 –

+0

我想要的是Groovy,Scala和Java 8等语言。是的,编程模型有点不同,它处理更多的不可变对象。我也希望能够做到这一点,而无需手动编码。 –