我正在使用谷歌测试来测试我的c++库,它可以进行像素转换和其他操作。
现在考虑一下我有这些模型参与测试。
using Models = testing::Types<ARGBNormalized, RGBNormalized, HSLNormalized,
HSVNormalized, YUVNormalized, YCCNormalized>;
当我需要测试转换时,我需要来自这些类型的两个不同的模型。
所以我创建了一个这样的结构。
template<typename Source, typename Dest>
struct ConversionTypes{
using SourceModelType = Source;
using DestModelType = Dest;
};
然后再加上这个。
using ConversionModels = testing::Types<ConversionTypes<ARGBNormalized,YCCNormalized>.....>;
如果模型的计数是n
,我将不得不在转换模型列表中写入n*(n-1)
类型。我有4个或3个颜色的模型并不重要,但我的程序中会有10个以上的模型,手工编写90个组合是疯狂的。那么,有没有办法从我已经写的Models
中以某种方式生成这些ConversionModels
?
使用Boost。Mp11,它所需要的只是一个额外的谓词。我们可以将转换写如下:
#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
>;
CCD_ 5将CCD_ 6应用于列表CCD_。结果是在与Models
相同种类的列表中产生的。因此我们得到了一个CCD_ 9。但是,由于您不想测试身份转换,我们使用mp_remove_if
来去掉形式ConversionTypes<T, T>
的所有元素(这就是我们为其定义的辅助谓词SameConversionTypes
(。
话虽如此,虽然这适用于GoogleTest主干,但上述操作可能会失败。这是因为谷歌测试仅在过去18个月左右才为Types
转换为使用可变模板。在此之前,它生成了一个testing::Types
模板,该模板需要大量参数(以模拟旧编译器的可变模板(。如果你使用稍微旧一点的GoogleTest版本,那么你仍然可以依靠boost::mp11
来度过难关,只需做一些改动。
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
是一个真正的可变类型列表。所以我们可以用它来定义一切,然后用mp_rename
来代替";外壳";。它将mp_list<A, ..., Z>
转换为::testing::Types<A, ..., Z>
。
剩下的唯一警告是要注意GTest的实现限制。它可能不支持长度为90个类型的类型列表。您可能需要在本地重新生成标头,以增加它可以支持的类型。