What I really want to do is to compare the performance of different algorithms which solve the same task in different ways. Such algorithms, in my example called apply_10_times
have sub algorithms, which shall be switchable, and also receive template arguments. They are called apply_x
and apply_y
in my example and get int SOMETHING
as template argument.
I think the solution would be to specify a template function as template parameter to another template function. Something like this, where template_function
is of course pseudo-code:
template<int SOMETHING>
inline void apply_x(int &a, int &b) {
// ...
}
template<int SOMETHING>
inline void apply_y(int &a, int &b) {
// ...
}
template<template_function APPLY_FUNCTION, int SOMETHING>
void apply_10_times(int &a, int &b) {
for (int i = 0; i < 10; i ) {
cout << SOMETHING; // SOMETHING gets used here directly as well
APPLY_FUNCTION<SOMETHING>(a, b);
}
}
int main() {
int a = 4;
int b = 7;
apply_10_times<apply_x, 17>(a, b);
apply_10_times<apply_y, 19>(a, b);
apply_10_times<apply_x, 3>(a, b);
apply_10_times<apply_y, 2>(a, b);
return 0;
}
I've read that it's not possible to pass a template function as a template parameter, so I can't pass APPLY_FUNCTION
this way. The solution, afaik, is to use a wrapping struct
, which is then called a functor, and pass the functor as a template argument. Here is what I got with this approach:
template<int SOMETHING>
struct apply_x_functor {
static inline void apply(int &a, int &b) {
// ...
}
};
template<int SOMETHING>
struct apply_y_functor {
static inline void apply(int &a, int &b) {
// ...
}
};
template<typename APPLY_FUNCTOR, int SOMETHING>
void apply_10_times(int &a, int &b) {
for (int i = 0; i < 10; i ) {
cout << SOMETHING; // SOMETHING gets used here directly as well
APPLY_FUNCTOR:: template apply<SOMETHING>(a, b);
}
}
This approach apparently works. However, the line APPLY_FUNCTOR:: template apply<SOMETHING>(a, b);
looks rather ugly to me. I'd prefer to use something like APPLY_FUNCTOR<SOMETHING>(a, b);
and in fact this seems possible by overloading the operator()
, but I couldn't get this to work. Is it possible and if so, how?
CodePudding user response:
As it is not clear why you need APPLY_FUNCTION
and SOMETHING
as separate template arguments, or why you need them as template arguments at all, I'll state the obvious solution, which maybe isn't applicable to your real case, but to the code in the question it is.
#include <iostream>
template<int SOMETHING>
inline void apply_x(int a, int b) {
std::cout << a << " " << b;
}
template<int SOMETHING>
inline void apply_y(int a, int b) {
std::cout << a << " " << b;
}
template<typename F>
void apply_10_times(int a, int b,F f) {
for (int i = 0; i < 10; i ) {
f(a, b);
}
}
int main() {
int a = 4;
int b = 7;
apply_10_times(a, b,apply_x<17>);
apply_10_times(a, b,apply_y<24>);
}
If you want to keep the function to be called as template argument you can use a function pointer as non-type template argument:
template<void(*F)(int,int)>
void apply_10_times(int a, int b) {
for (int i = 0; i < 10; i ) {
F(a, b);
}
}
int main() {
int a = 4;
int b = 7;
apply_10_times<apply_x<17>>(a, b);
apply_10_times<apply_y<24>>(a, b);
}
In any case I see no reason to have APPLY_FUNCTION
and SOMETHING
as separate template arguments. The only gain is more complex syntax which is exactly what you want to avoid. If you do need to infer SOMETHING
from an instantiation of either apply_x
or apply_y
, this is also doable without passing the template and its argument separately, though again you'd need to use class templates rather than function templates.
PS:
Ah, now I understand what you mean. Yes, apply_10_times() also uses SOMETHING directly. Sorry, I simplified the code in the question too much.
As mentioned above. This does still not imply that you need to pass them separately. You can deduce SOMETHING
from a apply_x<SOMETHING>
via partial template specialization. This however requires to use class templates not function templates:
#include <iostream>
template <int SOMETHING>
struct foo {};
template <int X>
struct bar {};
template <typename T>
struct SOMETHING;
template <template <int> class T,int V>
struct SOMETHING<T<V>> { static constexpr int value = V; };
int main() {
std::cout << SOMETHING< foo<42>>::value;
std::cout << SOMETHING< bar<42>>::value;
}
CodePudding user response:
What I really want to do is to compare the performance of different algorithms which solve the same task in different ways.
You should provide more details about that.
Your first step should be get familiar with Google Benchmark. There is as site which provides it online. This tool give proper patterns for your scenario.
In next step you must be aware that in C
and C
there is "as if rule" which allows optimizer do do wonderful things, but makes creation of good performance test extremely difficult. It is easy write test which doesn't measure actual production code.
Here is cppcon talk showing how many traps are hidden when doing a good performance test fro C code. So be very very careful.