Suppose I have a template of a function, say
template<typename T>
func(T a, T b, ...) {
...
for (const auto &single : group) {
...
auto c = GivenFunc1(a, b, single, ...);
... }
...
}
However, for T being a special type, say "SpecialType", I want c
being calculated by "GivenFunc2" rather than "GivenFunc1". However, I would not like to write a specialization for "SpecialType", since there will be a huge code duplication. So I want the template function being something like
template<typename T>
func(T a, T b, ...) {
...
for (const auto &single : group) {
...
auto c = (T == SpecialType) ? GivenFunc2(a, b, single, ...)
: GivenFunc1(a, b, single, ...);
... }
...
}
Of course, this code does not compile since "T == SpecialType" is not valid. So how do I write it in an elegant way?
It's as simple as:
auto c = std::is_same_v<T, SpecialType> ? GivenFunc2(a, b, single, ...)
: GivenFunc1(a, b, single, ...);
If you can't use C++17, replace std::is_same_v<...>
with std::is_same<...>::value
.
But for this approach to work, both function calls have to be valid for every T
you want to use, even if in reality one of them won't be executed.
If it's not the case, you can resort to if constexpr
:
your_type_here c;
if constexpr (std::is_same_v<T, SpecialType>)
c = GivenFunc2(a, b, single, ...);
else
c = GivenFunc1(a, b, single, ...);
(This works only in C++17.)
If you can use C++17, you can achieve the result in a very clean way (with constexpr
and is_same
):
template<typename T>
func(T a, T b, ...) {
// ...
if constexpr (std::is_same_v<T, SpecialType>) {
// call GivenFunc2
} else {
// call GivenFunc1
}
// ...
}
Pre C++17 you can achieve the same result using techniques such as SFINAE
or "TAG Dispatching".
Additionally, you can just specialize the portion of the code referring to the function call (easy and avoid code duplication).
A short example here:
template <typename T>
struct DispatcherFn {
auto operator()(const T&, int) {
// call GivenFunc1
}
};
template <>
struct DispatcherFn<SpecialType> {
auto operator()(const SpecialType&, int) {
// GivenFunc2
}
};
template <typename T>
void func(const T& t) {
// ... code ...
auto c = DispatcherFn<T>()(t, 49); // specialized call
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With