I have a template function that is specialized with two types, as:
class A () { /* ... */ };
class B () { /* ... */ };
template<class T>
void foo (T &out);
template<>
void foo<A> (A &out) { /* ... */ }
template<>
void foo<B> (B &out) { /* different code ... */ }
I either call foo with A or B depending on a run-time condition and I need to allocate either A or B before calling foo
. After calling foo
there needs to be other code that is the same with both A or B, resulting in something like this:
if (condition) {
A obj;
foo (obj);
/* code using obj */
} else {
B obj;
foo (obj);
/* same code using obj */
}
Since the only difference is in the declaration of obj, I would like to avoid repeating the same code, ideally like auto obj = condition ? A() : B();
which of course is not allowed run time. Is there any other way to obtain this in a clean way?
CodePudding user response:
The common code could be a function template, or a generic lambda (depending on how much code there is and how readable the result:
if (condition) {
A obj;
foo (obj);
/* code using obj */
} else {
B obj;
foo (obj);
/* same code using obj */
}
Could transform into something like:
auto common_code = [](auto && obj) {
foo(obj);
/* code using obj */
};
if (condition) {
common_code(A{});
} else {
common_code(B{});
}
Another thing worth noting, foo
does not need to be a template, and generally speaking, function template specializations are discouraged (as the specializations don't participate in overload resolution, and can be surprising).
You can just write two non-template foo
functions, one that takes A&
and the other that takes a B&
. This is simpler and more obvious code.
CodePudding user response:
If you're passing either an A
or B
object as an (in-)out argument for mostly common code with some select specialized behavior, simply add a function template that delegates the non-common work to foo
and contains the common work by itself.
template <typename T, typename = std::enable_if_t<std::is_same_v<T, A> ||
std::is_same_v<T, B>>>
void do_non_const_things_with_a_or_b(T &obj) {
foo(obj); // specialized for A or B
// common code for A and B
}
void f(bool condition) {
if (condition) {
A obj;
do_non_const_things_with_a_or_b(obj);
} else {
B obj;
do_non_const_things_with_a_or_b(obj);
}
}