Last active
February 12, 2023 09:13
-
-
Save furfurylic/c882203a4d233b86d364543495c240cb to your computer and use it in GitHub Desktop.
lab - tuple_transform
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Apply a function to each corresponding element of tuples and make a new tuple of the return values |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
cmake_minimum_required(VERSION 3.13) | |
project(test_tuple_transform CXX) | |
set(CMAKE_CXX_STANDARD 17) | |
set(CMAKE_CXX_STANDARD_REQUIRED ON) | |
set(CMAKE_CXX_EXTENSIONS OFF) | |
set_property(GLOBAL PROPERTY USE_FOLDERS ON) | |
enable_testing() | |
include(FetchContent) | |
FetchContent_Declare( | |
googletest | |
GIT_REPOSITORY https://github.com/google/googletest.git | |
GIT_TAG v1.13.0 | |
) | |
FetchContent_GetProperties(googletest) | |
if(NOT googletest_POPULATED) | |
FetchContent_Populate(googletest) | |
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) | |
add_subdirectory(${googletest_SOURCE_DIR} | |
${googletest_BINARY_DIR} | |
EXCLUDE_FROM_ALL) | |
endif() | |
set_target_properties(gtest gtest_main PROPERTIES FOLDER "Dependencies") | |
add_executable(test_tuple_transform) | |
target_sources(test_tuple_transform PRIVATE | |
tuple_transform.hpp | |
test_tuple_transform.cpp | |
) | |
target_compile_features(test_tuple_transform PRIVATE cxx_std_17) | |
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") | |
target_compile_options(test_tuple_transform PRIVATE | |
/MP /W4 /bigobj | |
$<$<CONFIG:MinSizeRel>:/wd4702> | |
$<$<CONFIG:Release>:/wd4702> | |
$<$<CONFIG:RelWithDebInfo>:/wd4702> | |
) | |
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") | |
target_compile_definitions(test_tuple_transform PRIVATE | |
$<$<NOT:$<CONFIG:Debug>>:NDEBUG> | |
) | |
target_compile_options(test_tuple_transform PRIVATE | |
-Wall -Wextra -pedantic-errors -Werror=pedantic | |
$<$<CONFIG:Debug>:-O0 -g3> | |
$<$<CONFIG:RelWithDebInfo>:-O2 -g3> | |
) | |
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") | |
target_compile_definitions(test_tuple_transform PRIVATE | |
$<$<NOT:$<CONFIG:Debug>>:NDEBUG> | |
) | |
target_compile_options(test_tuple_transform PRIVATE | |
-Wall -Wextra -pedantic-errors -Werror=pedantic | |
-Wno-gnu-zero-variadic-macro-arguments | |
$<$<CONFIG:Debug>:-O0 -g3> | |
$<$<CONFIG:RelWithDebInfo>:-O2 -g3> | |
) | |
endif() | |
target_link_libraries(test_tuple_transform PRIVATE gtest gtest_main) | |
add_test( | |
NAME test_tuple_transform | |
COMMAND $<TARGET_FILE:test_tuple_transform> | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* These codes are available under CC0 1.0 Universal. | |
* https://creativecommons.org/publicdomain/zero/1.0/deed | |
*/ | |
#include <functional> | |
#include <memory> | |
#include <string> | |
#include <tuple> | |
#include <type_traits> | |
#include <vector> | |
#include <gtest/gtest.h> | |
#include "tuple_transform.hpp" | |
using namespace std::literals::string_literals; | |
using namespace furfurylic::lab; | |
TEST(TestTupleTransform, Basics) { | |
auto t1 = std::make_tuple("break"s, 2); | |
auto t2 = std::make_tuple("fast"s, 3); | |
auto u = transform(std::plus<>(), t1, t2); | |
ASSERT_EQ(std::make_tuple("breakfast"s, 5), u); | |
} | |
TEST(TestTupleTransform, Move) { | |
std::tuple<std::unique_ptr<int>> t(new int(100)); | |
const auto pt = std::get<0>(t).get(); | |
auto u = transform([](std::unique_ptr<int>&& e1) { | |
std::vector<std::unique_ptr<int>> v; | |
v.push_back(std::move(e1)); | |
return v; | |
}, std::move(t)); | |
static_assert(std::is_same_v<std::tuple<std::vector<std::unique_ptr<int>>>, | |
decltype(u)>); | |
ASSERT_TRUE(!std::get<0>(t)); // moved-from state | |
ASSERT_EQ(pt, std::get<0>(u)[0].get()); // takes over the pointee of t | |
} | |
static_assert(std::make_tuple(6, 54.0) | |
== transform(std::multiplies<>(), | |
std::make_tuple(2, 9.0), std::make_tuple(3, 6.0))); | |
static_assert(std::is_same_v< | |
std::tuple<>, | |
decltype(transform(std::multiplies<>(), std::tuple<>()))>); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* These codes are available under CC0 1.0 Universal. | |
* https://creativecommons.org/publicdomain/zero/1.0/deed | |
*/ | |
#ifndef FURFURYLIC_LAB_GUARD_F0826CB7_4DF1_403B_8C6B_1CE6CA2D8619 | |
#define FURFURYLIC_LAB_GUARD_F0826CB7_4DF1_403B_8C6B_1CE6CA2D8619 | |
#include <algorithm> | |
#include <cstddef> | |
#include <tuple> | |
#include <type_traits> | |
#include <utility> | |
namespace furfurylic::lab { | |
namespace detail { | |
template <std::size_t I, class F, class... Tuples> | |
constexpr auto apply(F f, Tuples&&... t) { | |
return f(std::get<I>(std::forward<Tuples>(t))...); | |
} | |
template <std::size_t... Is, class F, class... Tuples> | |
constexpr auto transform_impl(std::index_sequence<Is...>, | |
[[maybe_unused]] F f, [[maybe_unused]] Tuples&&... ts) { | |
return std::make_tuple(apply<Is>(f, std::forward<Tuples>(ts)...)...); | |
} | |
} | |
template <class F, class... Tuples> | |
constexpr auto transform(F f, Tuples&&... ts) { | |
constexpr auto Min = std::min({std::tuple_size_v<std::decay_t<Tuples>>...}); | |
constexpr auto Max = std::max({std::tuple_size_v<std::decay_t<Tuples>>...}); | |
static_assert(Min == Max, "Inconsistent tuple sizes"); | |
return detail::transform_impl(std::make_index_sequence<Min>(), | |
std::move(f), std::forward<Tuples>(ts)...); | |
} | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment