Шаблон C ++ Template для модульного тестирования - PullRequest
0 голосов
/ 24 октября 2018

Я экспериментирую с использованием возможностей шаблонных шаблонов 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 Ответ

0 голосов
/ 24 октября 2018

Я экспериментирую с использованием шаблонных функций 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 () без использования шаблонов шаблона?

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

...