feat: simple pipeline

This commit is contained in:
Luís Murta 2025-08-06 21:07:05 +01:00
parent 0509c62bf1
commit 4d37acdda7
Signed by: satprog
GPG Key ID: 169EF1BBD7049F94
4 changed files with 110 additions and 2 deletions

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.20)
cmake_minimum_required(VERSION 3.20...4.0)
project(
pipeline_asio
pipe
VERSION 0.1.0
LANGUAGES CXX)
@ -9,5 +9,11 @@ find_package(fmt REQUIRED)
add_subdirectory(external/pipeline)
add_subdirectory(external/pipes)
# Specify the include directories include_directories(include)
add_library(pipe INTERFACE)
target_compile_features(pipe INTERFACE cxx_std_23)
target_include_directories(pipe INTERFACE include)
enable_testing()
add_subdirectory(tests)

View File

@ -0,0 +1,72 @@
// Copyright 2025, Luís Murta
// SPDX-License-Identifier: MIT
#pragma once
#include <any>
#include <concepts>
#include <functional>
#include <optional>
#include <ostream>
#include <tuple>
#include <utility>
namespace freepipe {
template <typename... Args> struct Task {
explicit constexpr Task(Args &&...args)
requires(sizeof...(Args) > 0)
: args_(std::forward<Args>(args)...) {}
explicit constexpr Task()
requires(sizeof...(Args) == 0)
{}
constexpr auto const &operator*() const & { return args_; }
constexpr auto &operator*() & { return args_; }
constexpr auto &&operator*() && { return std::move(args_); }
constexpr auto const &&operator*() const && { return std::move(args_); }
private:
std::tuple<Args...> args_;
};
template <typename... Args, std::regular_invocable<Args...> F>
constexpr auto operator|(Task<Args...> const &task, F &&func) {
using R = std::invoke_result_t<F, Args...>;
if constexpr (std::is_void_v<R>) {
std::apply(std::forward<F>(func), *task);
return Task<>{};
} else {
return Task<R>{std::apply(std::forward<F>(func), *task)};
}
}
template <typename... Args, std::regular_invocable<Args...> F>
constexpr auto operator|(Task<Args...> &&task, F &&func) {
using R = std::invoke_result_t<F, Args...>;
if constexpr (std::is_void_v<R>) {
std::apply(std::forward<F>(func), *std::move(task));
return Task<>{};
} else {
return Task<R>{std::apply(std::forward<F>(func), *std::move(task))};
}
}
template <typename... Args, typename CharT, typename Traits = std::char_traits<CharT>>
constexpr auto operator|(Task<Args...> const &task, std::basic_ostream<CharT, Traits> &os) {
std::apply([&os](auto &&...args) { ((os << args << '\n'), ...); }, *task);
return Task<>{};
}
template <typename... Args, typename CharT, typename Traits = std::char_traits<CharT>>
constexpr auto operator|(Task<Args...> &&task, std::basic_ostream<CharT, Traits> &os) {
std::apply([&os](auto &&...args) { ((os << args << '\n'), ...); }, *std::move(task));
return Task<>{};
}
class Pipe : public Task<> {};
} // namespace freepipe

View File

@ -5,3 +5,8 @@ target_compile_features(pipeline.test PUBLIC cxx_std_23)
target_link_libraries(pipeline.test benchmark::benchmark_main
pipeline::pipeline joboccara::pipes)
add_test(NAME pipeline.test COMMAND pipeline.test)
find_package(GTest REQUIRED)
add_executable(pipe.test pipe.test.cpp)
target_compile_features(pipe.test PUBLIC cxx_std_23)
target_link_libraries(pipe.test GTest::gtest_main pipe)

25
tests/pipe.test.cpp Normal file
View File

@ -0,0 +1,25 @@
#include <freepipe/freepipe.hpp>
#include <gtest/gtest.h>
#include <iostream>
namespace freepipe {
TEST(PipeTest, Single) {
Pipe p;
auto r = p | [] { return 42; } |
[](auto result) {
EXPECT_EQ(result, 42);
return result;
} |
std::cout |
[] {
SUCCEED();
return 0;
} |
[](auto result) { EXPECT_EQ(result, 0); } | [] { return 0; };
EXPECT_EQ(*r, std::tuple{0});
}
} // namespace freepipe