用于单元测试的 C++ Template 模板
C++ Template template for unit testing
我正在尝试使用 C++ 的模板模板功能来减少我代码中的一个小单元测试段中的代码重复,但没有成功。我已经看到 these answers 类似的问题,但仍然无法弄清楚我的编译器告诉我的是什么。
我处理一些以不同精度进行数值处理的 classes,所以我认为我可以将重复代码泛化为模板函数,这样它就可以很容易地被 class 测试,如:
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
,编译器都会拒绝并显示错误消息 "Invalid Template Argument for 'F', type expected",如下例所示:
void SomeClassTest::Test() const {
std::cerr << "Some Class Tests #1 - base/identity case" << std::endl;
CheckAgainstNumericTypes<SomeClassIdentity>();
...
我试着让 CheckAgainstNumericTypes
成为 SomeClass
的成员函数,在模板参数前面加上 SomeClass::
,在它的末尾添加 ()
,甚至替换内部 typedef
来自 void(*F)(void)
;都无济于事。
我有两个问题,那么:
- 如何将我的成员函数转换为一个类型以便它被模板接受?
- 是否有任何其他方法可以在
SomeClassTest::Tests()
中实现相同的语法结果而不使用 模板?
I'm experimenting with using C++'s template template features to reduce code duplication in a small unit test segment in my code, to no success
嗯...在我看来你还没有理解模板模板是什么。
如果我没理解错的话,你以为你写的时候
template <template <typename> typename F>
void CheckAgainstNumericTypes() {
F<char>();
}
您正在调用函数 F<char>()
。
错了。
即F<char>()
是创建F<char>
类型的临时对象,默认初始化。
你可以写F<char>{}
而不是F<char>()
,这样更清楚这不是模板函数的调用。
在这一点上,我不知道回应您的以下回答是否有意义,但是...
How can I transform my member function into a type so it is accepted by the template?
你不能。不是类型。
您可以在非类型模板参数中传递函数 - 或 class/struct 的静态成员(参见您链接的第一个答案)。
但是非静态方法(非静态成员函数)是另一种类型的野兽,需要 class 的对象才能调用它。
我能想到的最好的情况如下(注意:代码不是睾丸)
template <typename T, void (T::*M)()>
void foo (T & d)
{ d.*M(); }
你可以调用它
foo<SomeClassTest, &SomeClassTest::SomeClassIdentity>(someClassTestObject);
如您所见,您可以将 class 和指向方法的指针作为模板参数传递(类型模板参数第一个,值第二个)但是您需要一个类型的对象SomeClassTest
作为参数 (someClassTestObject
).
如果你只想与特定 class 的成员一起工作(SomeClassTest
,在你的情况下)你可以避免类型模板参数并简化如下
template <void (SomeClassTest::*M)()>
void foo (SomeClassTest & d)
{ d.*M(); }
// ...
foo<&SomeClassTest::SomeClassIdentity>(someClassTestObject);
Is there any other way of accomplishing the same desired syntactic result in SomeClassTest::Tests() without using template templates?
您不能使用模板-模板参数。
我正在尝试使用 C++ 的模板模板功能来减少我代码中的一个小单元测试段中的代码重复,但没有成功。我已经看到 these answers 类似的问题,但仍然无法弄清楚我的编译器告诉我的是什么。
我处理一些以不同精度进行数值处理的 classes,所以我认为我可以将重复代码泛化为模板函数,这样它就可以很容易地被 class 测试,如:
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
,编译器都会拒绝并显示错误消息 "Invalid Template Argument for 'F', type expected",如下例所示:
void SomeClassTest::Test() const {
std::cerr << "Some Class Tests #1 - base/identity case" << std::endl;
CheckAgainstNumericTypes<SomeClassIdentity>();
...
我试着让 CheckAgainstNumericTypes
成为 SomeClass
的成员函数,在模板参数前面加上 SomeClass::
,在它的末尾添加 ()
,甚至替换内部 typedef
来自 void(*F)(void)
;都无济于事。
我有两个问题,那么:
- 如何将我的成员函数转换为一个类型以便它被模板接受?
- 是否有任何其他方法可以在
SomeClassTest::Tests()
中实现相同的语法结果而不使用 模板?
I'm experimenting with using C++'s template template features to reduce code duplication in a small unit test segment in my code, to no success
嗯...在我看来你还没有理解模板模板是什么。
如果我没理解错的话,你以为你写的时候
template <template <typename> typename F>
void CheckAgainstNumericTypes() {
F<char>();
}
您正在调用函数 F<char>()
。
错了。
即F<char>()
是创建F<char>
类型的临时对象,默认初始化。
你可以写F<char>{}
而不是F<char>()
,这样更清楚这不是模板函数的调用。
在这一点上,我不知道回应您的以下回答是否有意义,但是...
How can I transform my member function into a type so it is accepted by the template?
你不能。不是类型。
您可以在非类型模板参数中传递函数 - 或 class/struct 的静态成员(参见您链接的第一个答案)。
但是非静态方法(非静态成员函数)是另一种类型的野兽,需要 class 的对象才能调用它。
我能想到的最好的情况如下(注意:代码不是睾丸)
template <typename T, void (T::*M)()>
void foo (T & d)
{ d.*M(); }
你可以调用它
foo<SomeClassTest, &SomeClassTest::SomeClassIdentity>(someClassTestObject);
如您所见,您可以将 class 和指向方法的指针作为模板参数传递(类型模板参数第一个,值第二个)但是您需要一个类型的对象SomeClassTest
作为参数 (someClassTestObject
).
如果你只想与特定 class 的成员一起工作(SomeClassTest
,在你的情况下)你可以避免类型模板参数并简化如下
template <void (SomeClassTest::*M)()>
void foo (SomeClassTest & d)
{ d.*M(); }
// ...
foo<&SomeClassTest::SomeClassIdentity>(someClassTestObject);
Is there any other way of accomplishing the same desired syntactic result in SomeClassTest::Tests() without using template templates?
您不能使用模板-模板参数。