73 lines
2.1 KiB
C++
73 lines
2.1 KiB
C++
// 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
|