Template function as a template argument
With generic lambda from C++14 you might do:
template<typename T> void a(T t) { /* do something */}
template<typename T> void b(T t) { /* something else */ }
template <typename F>
void function(F&& f) {
f(someobj);
f(someotherobj);
}
void test() {
// For simple cases, auto&& is even probably auto or const auto&
function([](auto&& t){ a(t); });
function([](auto&& t){ b(t); });
// For perfect forwarding
function([](auto&& t){ a(std::forward<decltype(t)>(t)); });
function([](auto&& t){ b(std::forward<decltype(t)>(t)); });
}
Can compilers still inline the calls if they are made via function pointers?
They can, but it is indeed more complicated, and they may fail more often than with functor or template.
Kos
MRW they close a question while I'm still answering Software developer, dilettante musician, bookworm. Enjoys tea, Python, piano, chiptune, functional programming and innovation.
Updated on June 26, 2022Comments
-
Kos almost 2 years
I've just got confused how to implement something in a generic way in C++. It's a bit convoluted, so let me explain step by step.
Consider such code:
void a(int) { // do something } void b(int) { // something else } void function1() { a(123); a(456); } void function2() { b(123); b(456); } void test() { function1(); function2(); }
It's easily noticable that
function1
andfunction2
do the same, with the only different part being the internal function.Therefore, I want to make
function
generic to avoid code redundancy. I can do it using function pointers or templates. Let me choose the latter for now. My thinking is that it's better since the compiler will surely be able to inline the functions - am I correct? Can compilers still inline the calls if they are made via function pointers? This is a side-question.OK, back to the original point... A solution with templates:
void a(int) { // do something } void b(int) { // something else } template<void (*param)(int) > void function() { param(123); param(456); } void test() { function<a>(); function<b>(); }
All OK. But I'm running into a problem: Can I still do that if
a
andb
are generics themselves?template<typename T> void a(T t) { // do something } template<typename T> void b(T t) { // something else } template< ...param... > // ??? void function() { param<SomeType>(someobj); param<AnotherType>(someotherobj); } void test() { function<a>(); function<b>(); }
I know that a template parameter can be one of:
- a type,
- a template type,
- a value of a type.
None of those seems to cover my situation. My main question is hence: How do I solve that, i.e. define
function()
in the last example?(Yes, function pointers seem to be a workaround in this exact case - provided they can also be inlined - but I'm looking for a general solution for this class of problems).
-
Kos over 13 yearsBut please note that
function
will want to call different instantiations of the parameter template function. -
visual_learner over 13 years@Kos - Is
#define
out of the question? -
visual_learner over 13 yearsThis isn't what the OP wanted.
-
Kos over 13 yearsThanks, but this is unrelated to the problem I've described. In this case, a given
function
call only uses 1 instantiation of a parameter function/functor. Please read the question once again. -
Kos over 13 yearsWell, it is a "last resort" which would work :), but it's uncomfortable to edit, debug, can't be in a namespace... I'd prefer to find a template-based not preprocessor-based solution.
-
mariusm over 4 yearsGeneric lambdas are part of C++14.
-
Jarod42 over 4 years@mariusm: Indeed, wording fixed.