Reputation: 434
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:
SomeClassTest::Tests()
without using template templates?Upvotes: 1
Views: 1794
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