MVittiS
MVittiS

Reputation: 434

C++ Template template for unit testing

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. I've seen these answers to similar questions, but still can't figure out what my compiler is telling me.

I deal with some classes that do numerical processing at different precisions, and so I thought that I could generalize the duplicate code to a templated function, so it could be easily called by the class tests, as in:

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
}

And then, test a lot of operations similar to SomeClassTest::SomeClassIdentity with a template template function:

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>();
}

The problem is, every time I try to invoke CheckAgainstNumericTypes, the compiler will refuse with the error message "Invalid Template Argument for 'F', type expected", as in the example below:

void SomeClassTest::Test() const {
    std::cerr << "Some Class Tests #1 - base/identity case" << std::endl;
    CheckAgainstNumericTypes<SomeClassIdentity>();
    ...

I tried making CheckAgainstNumericTypes a member function of SomeClass, prepending the template argument with SomeClass::, adding () to the end of it, and even replacing the inner typedef by void(*F)(void); all to no avail.

I have two questions, then:

Upvotes: 1

Views: 1794

Answers (1)

max66
max66

Reputation: 66210

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

Well... it seems to me that you haven't understand what a template-template is.

If I understand correctly, you think that when you write

template <template <typename> typename F>
void CheckAgainstNumericTypes() {
    F<char>();
}

you're calling a function F<char>().

Wrong.

That F<char>() is the creation of a temporary object of type F<char>, default initialized.

Instead of F<char>(), you can write F<char>{}, so it's more clear that this isn't a call of a template function.

At this point, I don't know if make sense to respond to your following answer but...

How can I transform my member function into a type so it is accepted by the template?

You can't. Not as type.

You can pass a function - or a static member of a class/struct, in a not-type template argument (see first answer you linked).

But a non static method (a non static member function) is another type of beast and require a object of the class to call it.

The best I can imagine is something as follows (caution: code not testes)

template <typename T, void (T::*M)()>
void foo (T & d)
 { d.*M(); }

and you can call it

foo<SomeClassTest, &SomeClassTest::SomeClassIdentity>(someClassTestObject);

As you can see, you can pass the class and the pointer to the method as template parameters (a type template parameters the first one, a value the second one) but you need an object of type SomeClassTest as argument (someClassTestObject).

If you want to works only with members of a specific class (SomeClassTest, in you case) you can avoid the type template argument and simplify as follows

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?

You can't using template-template parameters.

Upvotes: 3

Related Questions