With Boost.Mp11, all it takes is a little extra predicate. We can write the transformation as follows:
#include <type_traits>
#include <gtest/gtest.h>
#include <boost/mp11/algorithm.hpp>
template<typename Source, typename Dest>
struct ConversionTypes {
using SourceModelType = Source;
using DestModelType = Dest;
};
template<typename> struct SameConversionTypes : std::false_type{};
template<typename T> struct SameConversionTypes<ConversionTypes<T, T>> : std::true_type{};
using Models = ::testing::Types<char, int, long, long long>;
using ConversionModels =
boost::mp11::mp_remove_if<
boost::mp11::mp_product<ConversionTypes, Models, Models>,
SameConversionTypes
>;
mp_product
applies ConversionTypes
to the Cartesian product of the list Models
with itself. The result is produced in the same sort of list as Models
. So we obtain a ::testing::Types<ConversionTypes<...>...>
. However, since you do not want to test the identity conversion, we use mp_remove_if
to get rid of all elements of the form ConversionTypes<T, T>
(which is what we defined the helper predicate SameConversionTypes
for).
Having said that, while this works with the GoogleTest trunk, the above may fail for you. That is because google test only switched to using variadic templates for Types
only in the last 18 months or so. Prior it generated a testing::Types
template that took a very large number of arguments (to simulate variadic templates for older compilers). If you use a slightly older version of GoogleTest, then you can still rely on boost::mp11
to get by, with a little alteration.
using Models_ = boost::mp11::mp_list<char, int, long, long long>;
using Models = boost::mp11::mp_rename<Models_, ::testing::Types>;
using ConversionModels =
boost::mp11::mp_rename<
boost::mp11::mp_remove_if<
boost::mp11::mp_product<ConversionTypes, Models_, Models_>,
SameConversionTypes
>,
::testing::Types
>;
mp_list
is a truly variadic type list. So we can define everything in terms of it, and then use mp_rename
to replace the "outer shell". It turns mp_list<A, ..., Z>
into ::testing::Types<A, ..., Z>
.
Only caveat remaining is to be mindful of GTest's implementation limits. It may not support a type list that is 90 types long. You may need to regenerate the header locally to increase how many types it can support.