c++ - 用于单元测试的 C++ 模板模板
问题描述
我正在尝试使用 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::
,添加()
到它的末尾,甚至用 ; 替换typedef
内部void(*F)(void)
。一切都无济于事。
那我有两个问题:
- 如何将我的成员函数转换为类型以便模板接受它?
- 有没有其他方法可以在
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() 中实现相同的语法结果而不使用模板模板?
您不能使用模板模板参数。
推荐阅读
- npm - Atom 使用 npm live-server 保存时不会自动重新加载
- c# - C#如何禁用任务计划程序中的某些设置字段
- javascript - 你如何改变从同一个类中渲染的 jsx 块?
- sql - PostgreSQL 不在多个通配符中
- javascript - 我如何将 react-native 移动应用程序连接到 Django
- python - Django 服务器没有运行
- java - startActivityForResult 并在活动完成时继续
- node.js - 如何在 Google App Engine 标准环境中使用 Google Cloud Build 或其他方法设置环境变量?
- c# - 隐藏网格元素时更改 GridSplitter 行为
- java - 如何在android Studio中伪装android xml可点击链接?