Шаблон C++ Template для модульного тестирования
Я экспериментирую с использованием возможностей шаблонных шаблонов 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()
без использования шаблонов?
1 ответ
Я экспериментирую с использованием шаблонных функций 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() без использования шаблонов?
Вы не можете использовать параметры шаблона-шаблона.