Raw File
TestTMP.cpp
/**
 * \file
 * \copyright
 * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
 *            Distributed under a Modified BSD License.
 *              See accompanying file LICENSE.txt or
 *              http://www.opengeosys.org/project/license
 *
 */

#include <gmock/gmock-matchers.h>
#include <gtest/gtest.h>

#include <tuple>

#include "BaseLib/TMP.h"

TEST(BaseLibTMP, Concat)
{
    namespace T = BaseLib::TMP;

    // empty lists
    {
        using Expected = std::tuple<>;
        using First = std::tuple<>;
        using Second = std::tuple<>;
        using Actual = T::Concat_t<First, Second>;
        static_assert(std::is_same_v<Expected, Actual>);
    }

    // single-element and empty
    {
        using Expected = std::tuple<double>;
        using First = std::tuple<double>;
        using Second = std::tuple<>;
        using Actual = T::Concat_t<First, Second>;
        static_assert(std::is_same_v<Expected, Actual>);
    }

    // empty and single-element
    {
        using Expected = std::tuple<int>;
        using First = std::tuple<>;
        using Second = std::tuple<int>;
        using Actual = T::Concat_t<First, Second>;
        static_assert(std::is_same_v<Expected, Actual>);
    }

    // twice the same
    {
        using Expected = std::tuple<unsigned, unsigned>;
        using First = std::tuple<unsigned>;
        using Second = std::tuple<unsigned>;
        using Actual = T::Concat_t<First, Second>;
        static_assert(std::is_same_v<Expected, Actual>);
    }

    // two lists
    {
        using Expected = std::tuple<double, std::string, int, char>;
        using First = std::tuple<double, std::string>;
        using Second = std::tuple<int, char>;
        using Actual = T::Concat_t<First, Second>;
        static_assert(std::is_same_v<Expected, Actual>);
    }
}

TEST(BaseLibTMP, Filter)
{
    namespace T = BaseLib::TMP;

    // empty list
    {
        using Expected = T::List<>;
        using List = std::tuple<>;
        auto pred = [](auto*) { return true; };
        using Actual = decltype(T::filter<List>(pred));
        static_assert(std::is_same_v<Expected, Actual>);
    }

    // keep all
    {
        using Expected = T::List<int, double, std::string>;
        using List = std::tuple<int, double, std::string>;
        auto pred = [](auto*) { return true; };
        using Actual = decltype(T::filter<List>(pred));
        static_assert(std::is_same_v<Expected, Actual>);
    }

    // keep none
    {
        using Expected = T::List<>;
        using List = std::tuple<int, double, std::string>;
        auto pred = [](auto*) { return false; };
        using Actual = decltype(T::filter<List>(pred));
        static_assert(std::is_same_v<Expected, Actual>);
    }

    // keep some
    {
        using Expected = T::List<int, unsigned, char>;
        using List = std::tuple<int, double, unsigned, std::string, char>;
        auto pred = []<typename T>(T*) { return std::is_integral_v<T>; };
        using Actual = decltype(T::filter<List>(pred));
        static_assert(std::is_same_v<Expected, Actual>);
    }
}

TEST(BaseLibTMP, Map)
{
    namespace T = BaseLib::TMP;

    // empty list
    {
        using Expected = std::tuple<>;
        using List = std::tuple<>;
        using Actual = T::Map_t<std::add_pointer_t, List>;
        static_assert(std::is_same_v<Expected, Actual>);
    }

    // non-empty list
    {
        using Expected = std::tuple<int*, double*, std::string*>;
        using List = std::tuple<int, double, std::string>;
        using Actual = T::Map_t<std::add_pointer_t, List>;
        static_assert(std::is_same_v<Expected, Actual>);
    }
}

TEST(BaseLibTMP, MapToArray)
{
    namespace T = BaseLib::TMP;

    // empty list
    {
        using Expected = std::array<std::nullptr_t, 0>;
        using List = std::tuple<>;
        auto mapping = [](auto*) { return 0; };
        auto actual = T::map_to_array<List>(mapping);
        static_assert(std::is_same_v<Expected, decltype(actual)>);
    }

    // non-empty list
    {
        std::array<bool, 5> expected{true, false, true, false, true};
        using List = std::tuple<int, double, unsigned, std::string, char>;
        auto mapping = []<typename T>(T*) { return std::is_integral_v<T>; };
        auto actual = T::map_to_array<List>(mapping);
        EXPECT_THAT(actual, testing::ContainerEq(expected));
    }
}

TEST(BaseLibTMP, ForEach)
{
    namespace T = BaseLib::TMP;

    // empty list
    {
        std::vector<bool> expected{};

        using List = std::tuple<>;
        std::vector<bool> actual{};
        auto callback = [&actual](auto*) { actual.push_back(true); };

        T::foreach<List>(callback);

        EXPECT_TRUE(actual.empty());
    }

    // non-empty list
    {
        std::vector<bool> expected{true, false, true, false, true};

        using List = std::tuple<int, double, unsigned, std::string, char>;
        std::vector<bool> actual{};
        auto callback = [&actual]<typename T>(T*)
        { actual.push_back(std::is_integral_v<T>); };

        T::foreach<List>(callback);

        EXPECT_THAT(actual, testing::ContainerEq(expected));
    }
}

TEST(BaseLibTMP, Contains)
{
    namespace T = BaseLib::TMP;

    // empty list
    {
        using List = std::tuple<>;
        using Type = double;
        auto constexpr actual = T::contains<List, Type>();
        static_assert(!actual);
    }

    // found
    {
        using List = std::tuple<int, double, unsigned, std::string, char>;
        static_assert(T::contains<List, int>());
        static_assert(T::contains<List, double>());
        static_assert(T::contains<List, char>());
    }

    // not found
    {
        using List = std::tuple<int, double, unsigned, std::string, char>;
        static_assert(!T::contains<List, unsigned char>());
    }
}
back to top