caldfir
caldfir

Reputation: 414

C++ templated subclass arguments to templated function

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

Answers (1)

cigien
cigien

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

Related Questions