Шаблон 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() без использования шаблонов?

Вы не можете использовать параметры шаблона-шаблона.

Другие вопросы по тегам