diff --git a/library/phx/container_tuple.hpp b/library/phx/container_tuple.hpp new file mode 100644 index 0000000000000000000000000000000000000000..abaf79715dbf5a48b6944cddf5622315e59fb246 --- /dev/null +++ b/library/phx/container_tuple.hpp @@ -0,0 +1,77 @@ +//------------------------------------------------------------------------------ +// Project Phoenix +// +// Copyright (c) 2017-2018 RWTH Aachen University, Germany, +// Virtual Reality & Immersive Visualization Group. +//------------------------------------------------------------------------------ +// License +// +// Licensed under the 3-Clause BSD License (the "License"); +// you may not use this file except in compliance with the License. +// See the file LICENSE for the full text. +// You may obtain a copy of the License at +// +// https://opensource.org/licenses/BSD-3-Clause +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//------------------------------------------------------------------------------ + +#ifndef LIBRARY_PHX_CONTAINER_TUPLE_HPP_ +#define LIBRARY_PHX_CONTAINER_TUPLE_HPP_ + +#include <cstddef> +#include <tuple> +#include <type_traits> +#include <vector> + +namespace phx { +template <typename... Types> +class ContainerTuple { + public: + virtual ~ContainerTuple() = default; + + template <typename Type> + using ContainerType = std::vector<Type>; + + template <typename Type> + const ContainerType<Type>* Get() const { + return Find<0, Type, std::tuple<ContainerType<Types>...>, + IsSame<0, Type>::value>::Get(containers_); + } + template <typename Type> + ContainerType<Type>* Get() { + return Find<0, Type, std::tuple<ContainerType<Types>...>, + IsSame<0, Type>::value>::Get(containers_); + } + + protected: + template <std::size_t Index, typename Type> + struct IsSame + : std::is_same< + Type, + typename std::tuple_element< + Index, std::tuple<ContainerType<Types>...>>::type::value_type> { + }; + template <std::size_t Index, typename Type, typename Tuple, + bool Match = false> + struct Find { + static ContainerType<Type>* Get(const Tuple& value) { + return Find<Index + 1, Type, Tuple, IsSame<Index + 1, Type>::value>::Get( + value); + } + }; + template <std::size_t Index, typename Type, typename Tuple> + struct Find<Index, Type, Tuple, true> { + static ContainerType<Type>* Get(const Tuple& value) { + return const_cast<ContainerType<Type>*>(&std::get<Index>(value)); + } + }; + + std::tuple<ContainerType<Types>...> containers_; +}; +} // namespace phx +#endif // LIBRARY_PHX_CONTAINER_TUPLE_HPP_ diff --git a/tests/src/test_container_tuple.cpp b/tests/src/test_container_tuple.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5a2a0aa0a2349a4de9416179af4e1f431868ffc5 --- /dev/null +++ b/tests/src/test_container_tuple.cpp @@ -0,0 +1,68 @@ +//------------------------------------------------------------------------------ +// Project Phoenix +// +// Copyright (c) 2017-2018 RWTH Aachen University, Germany, +// Virtual Reality & Immersive Visualization Group. +//------------------------------------------------------------------------------ +// License +// +// Licensed under the 3-Clause BSD License (the "License"); +// you may not use this file except in compliance with the License. +// See the file LICENSE for the full text. +// You may obtain a copy of the License at +// +// https://opensource.org/licenses/BSD-3-Clause +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//------------------------------------------------------------------------------ + +#include <string> +#include <vector> + +#include "catch/catch.hpp" + +#include "phx/container_tuple.hpp" + +SCENARIO("A container tuple is a tuple of containers accessible by type.", + "[phx][phx::ContainerTuple]") { + std::vector<int> test_values_int{{1, 2, 3, 4}}; + std::vector<float> test_values_float{{1.0F, 2.0F, 3.0F, 4.0F}}; + std::vector<std::string> test_values_string{{"a", "b", "c", "d"}}; + + GIVEN("A container tuple of int, float and std::string.") { + phx::ContainerTuple<int, float, std::string> container_tuple; + + WHEN("Access the integer container and set it to 1, 2, 3, 4.") { + auto int_container = container_tuple.Get<int>(); + int_container->assign(test_values_int.begin(), test_values_int.end()); + THEN("The integer container is set to 1, 2, 3, 4.") { + auto int_container_2 = container_tuple.Get<int>(); + REQUIRE(*int_container_2 == test_values_int); + } + } + + WHEN("Access the float container and set it to 1.0F, 2.0F, 3.0F, 4.0F.") { + auto float_container = container_tuple.Get<float>(); + float_container->assign(test_values_float.begin(), + test_values_float.end()); + THEN("The float container is set to 1.0F, 2.0F, 3.0F, 4.0F.") { + auto float_container_2 = container_tuple.Get<float>(); + REQUIRE(*float_container_2 == test_values_float); + } + } + + WHEN("Access the std::string container and set it to a, b, c, d.") { + auto string_container = container_tuple.Get<std::string>(); + string_container->assign(test_values_string.begin(), + test_values_string.end()); + THEN("The std::string container is set to a, b, c, d.") { + auto string_container_2 = container_tuple.Get<std::string>(); + REQUIRE(*string_container_2 == test_values_string); + } + } + } +}