Reputation: 414
I have a free function that I would like to overload/specialize for a large number of possible types, plus a degraded "fallback" using a template. Some of the classes I want to pass as arguments are themselves templates, or are descended from template-classes.
My problem is that compilation is favoring my fallback template over a parent-class specialization, as is illustrated in the sample below. I believe this is due to the template-parameter deduction creating an exact type-match with the less specific function, and while the compiler prefers non-templates, since both functions are templates it is selecting the fallback.
Is there a way to artificially raise or lower the precedence of the two templated functions while still using parameter deduction?
#include <gtest/gtest.h>
// parent template
template <typename T>
class Alice {};
// child of template
template <typename T>
class Bob : public Alice<T> {};
// fallback
template <typename D>
char bar(const D& d) { return 'D'; }
// specialization
template <typename E>
char bar(const Alice<E>& e) { return 'E'; }
TEST(Precedence, 0)
{
int i;
ASSERT_EQ(bar(i), 'D');
Alice<int> a;
ASSERT_EQ(bar(a), 'E');
Bob<int> b;
ASSERT_EQ(bar<int>(b), 'E');
ASSERT_EQ(bar(b), 'E'); // FAIL - gets 'D'
}
Upvotes: 2
Views: 47
Reputation: 60238
You can constrain the specialization to exactly accept template types that are derived from Alice
with the same template parameter:
// specialization
template <typename T, template<typename> typename Child>
typename std::enable_if_t<std::is_base_of_v<Alice<T>, Child<T>>, char>
bar(const Child<T>& e) { return 'E'; }
Here's a demo.
Upvotes: 1