C++ 用于单元测试的模板模板

C++ Template template for unit testing

本文关键字:单元测试 用于 C++      更新时间:2023-10-16

我正在尝试使用C++的模板模板功能来减少代码中一个小单元测试段中的代码重复,但没有成功。我已经看到了类似问题的答案,但仍然无法弄清楚我的编译器在告诉我什么。

我处理一些以不同精度进行数值处理的类,因此我认为我可以将重复的代码推广到模板化函数,以便类测试可以轻松调用它,如下所示:

template<typename T, size_t S>
void CompareArrays(
std::array<T, S> const &input,
std::array<T, S> const &output) {...}
template <typename T>
void SomeClassTest::SomeClassIdentity() const {
SomeClass<T> scZero;
std::array<T, 1> const input = { 1 };
auto output = scZero.Process(input);
CompareArrays(input, output); // does the actual printing
}

然后,使用模板模板函数测试许多类似于SomeClassTest::SomeClassIdentity的操作:

template<template <typename> typename F>
void CheckAgainstNumericTypes() {
std::cerr << "Testing with char...";
F<char>();
std::cerr << "Testing with short...";
F<short>();
std::cerr << "Testing with int...";
F<int>();
std::cerr << "Testing with float...";
F<float>();
std::cerr << "Testing with double...";
F<double>();
}

问题是,每次我尝试调用CheckAgainstNumericTypes时,编译器都会拒绝错误消息"'F'的模板参数无效,预期类型",如下例所示:

void SomeClassTest::Test() const {
std::cerr << "Some Class Tests #1 - base/identity case" << std::endl;
CheckAgainstNumericTypes<SomeClassIdentity>();
...

我尝试将CheckAgainstNumericTypes作为SomeClass的成员函数,在模板参数前面加上SomeClass::,在其末尾添加(),甚至用void(*F)(void)替换内部typedef;都无济于事。

那么,我有两个问题:

  • 如何将成员函数转换为类型,以便模板接受它?
  • 有没有其他方法可以在不使用模板模板的情况下SomeClassTest::Tests()中实现相同的所需语法结果?

我正在尝试使用 C++ 的模板模板功能来减少代码中小型单元测试段中的代码重复,但没有成功

井。。。在我看来,您还没有了解模板模板是什么。

如果我理解正确,你认为当你写的时候

template <template <typename> typename F>
void CheckAgainstNumericTypes() {
F<char>();
}

您正在调用函数F<char>().

错。

F<char>()是创建类型为F<char>的临时对象,默认初始化。

代替F<char>(),你可以写F<char>{},所以更清楚这不是对模板函数的调用。

在这一点上,我不知道回应你的以下答案是否有意义,但是......

如何将成员函数转换为类型,以便模板接受它?

你不能。不是类型。

您可以在非类型模板参数中传递函数或类/结构的静态成员(请参阅您链接的第一个答案(。

但是非静态方法(非静态成员函数(是另一种类型的野兽,需要类的对象来调用它。

我能想象的最好的是以下内容(注意:代码不是测试(

template <typename T, void (T::*M)()>
void foo (T & d)
{ d.*M(); }

你可以称之为

foo<SomeClassTest, &SomeClassTest::SomeClassIdentity>(someClassTestObject);

如您所见,您可以将类和指向方法的指针作为模板参数传递(第一个类型模板参数,第二个值(,但您需要一个类型为SomeClassTest的对象作为参数 (someClassTestObject(。

如果您只想使用特定类的成员(在您的情况下是SomeClassTest(,则可以避免使用类型模板参数并简化如下

template <void (SomeClassTest::*M)()>
void foo (SomeClassTest & d)
{ d.*M(); }
// ...
foo<&SomeClassTest::SomeClassIdentity>(someClassTestObject);

有没有其他方法可以在不使用模板模板的情况下在 SomeClassTest::Tests(( 中完成相同的所需语法结果?

不能使用模板模板参数。