You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++11/14是否支持Groovy风格的集合链式Lambda调用?

Great question! Let's break down how to replicate Groovy's fluent collection operations in C++11/14, including both existing solutions and custom implementation options.

First: The C++ Standard Library Reality

C++11/14's standard library doesn't offer Groovy-style chained member functions for collections out of the box. Instead, it uses standalone algorithms (like std::for_each, std::transform, std::copy_if) that operate on iterators, which means you'll need intermediate containers for multi-step operations.

For example, your Groovy code:

["a", "b"].each { println(it) }
[1, 2].collect { it * 2 }.grep { it % 3 }.each { println(it) }

Translates to standard C++ like this:

#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>

// Equivalent of ["a", "b"].each
std::vector<std::string> strs = {"a", "b"};
std::for_each(strs.begin(), strs.end(), [](const auto& s) {
    std::cout << s << '\n';
});

// Equivalent of [1,2].collect(...).grep(...).each
std::vector<int> nums = {1, 2};
std::vector<int> doubled;
std::transform(nums.begin(), nums.end(), std::back_inserter(doubled), [](int i) {
    return i * 2;
});

std::vector<int> filtered;
std::copy_if(doubled.begin(), doubled.end(), std::back_inserter(filtered), [](int i) {
    return i % 3 == 0;
});

std::for_each(filtered.begin(), filtered.end(), [](int i) {
    std::cout << i << '\n';
});

This works, but it's far less concise or fluent than Groovy's syntax.

Existing Libraries for Fluent Operations

If you don't want to roll your own, there are mature third-party libraries that add exactly this kind of chained, Groovy-like functionality:

1. Boost.Range

Boost.Range is a widely used library that extends the standard library with range-based operations, including chained adapters. Your example would look like this:

#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <vector>
#include <iostream>

using namespace boost::adaptors;
using namespace boost::range;

// Equivalent of ["a", "b"].each
std::vector<std::string> strs = {"a", "b"};
for_each(strs, [](const auto& s) { std::cout << s << '\n'; });

// Equivalent of [1,2].collect(...).grep(...).each
std::vector<int> nums = {1, 2};
for_each(
    nums | transformed([](int i) { return i * 2; }) 
         | filtered([](int i) { return i % 3 == 0; }),
    [](int i) { std::cout << i << '\n'; }
);

It uses the | operator to chain adapters (transformed = Groovy's collect, filtered = Groovy's grep) and keeps the code concise.

2. Range-v3

Range-v3 is the precursor to C20's standard ranges library, and it works perfectly in C11/14. It supports lazy evaluation (no intermediate containers unless you want them) and has a very natural fluent syntax:

#include <range/v3/all.hpp>
#include <vector>
#include <iostream>

using namespace ranges;

// Equivalent of ["a", "b"].each
std::vector<std::string> strs = {"a", "b"};
strs | actions::for_each([](const auto& s) { std::cout << s << '\n'; });

// Equivalent of [1,2].collect(...).grep(...).each
std::vector<int> nums = {1, 2};
nums | views::transform([](int i) { return i * 2; })
     | views::filter([](int i) { return i % 3 == 0; })
     | actions::for_each([](int i) { std::cout << i << '\n'; });

This is almost identical to the syntax you envisioned, just using | instead of dot notation for chaining.

Rolling Your Own Custom Collection Class

If you want full control over the syntax (matching your exact Collection({...}).Each(...) idea), you can easily implement a wrapper class. Here's a minimal working example:

#include <vector>
#include <functional>
#include <iostream>

template<typename T>
class Collection {
private:
    std::vector<T> data;

public:
    // Initialize from initializer list
    Collection(std::initializer_list<T> init) : data(init) {}
    // Initialize from existing vector
    Collection(std::vector<T> vec) : data(std::move(vec)) {}

    // Each: Iterate and apply a function
    Collection& Each(std::function<void(const T&)> func) {
        for (const auto& elem : data) {
            func(elem);
        }
        return *this;
    }

    // Collect: Transform elements into a new Collection
    template<typename U>
    Collection<U> Collect(std::function<U(const T&)> func) const {
        std::vector<U> new_data;
        new_data.reserve(data.size());
        for (const auto& elem : data) {
            new_data.push_back(func(elem));
        }
        return Collection<U>(std::move(new_data));
    }

    // Grep: Filter elements into a new Collection
    Collection Grep(std::function<bool(const T&)> func) const {
        std::vector<T> new_data;
        for (const auto& elem : data) {
            if (func(elem)) {
                new_data.push_back(elem);
            }
        }
        return Collection(std::move(new_data));
    }
};

// Test your exact desired syntax
int main() {
    Collection<std::string>{"a", "b"}.Each([](const auto& s) {
        std::cout << s << '\n';
    });

    Collection<int>{1, 2}
        .Collect([](int i) { return i * 2; })
        .Grep([](int i) { return i % 3 == 0; })
        .Each([](int i) { std::cout << i << '\n'; });

    return 0;
}

This implementation matches your proposed syntax exactly. You can extend it further (add a Range class, support lazy evaluation, or handle more container types) based on your needs.

Final Takeaway

  • C++11/14 standard library doesn't have native fluent collection operations, but you can use standalone algorithms.
  • Third-party libraries like Boost.Range or Range-v3 provide battle-tested, efficient implementations of the syntax you want.
  • Writing your own Collection wrapper is straightforward if you need full control over the API.

内容的提问来源于stack exchange,提问作者dromodel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:13:21