Ghostrider
Ghostrider

Reputation: 7775

template class that derives from same template

I have an equivalent to following code:

struct Empty {
  static constexpr int id = 0;
};

template <typename Self, typename Base = Empty> struct Compound : public Base
{
  int get_id() const
  {
    return Self::id;
  }
};

struct A : Compound<A>
{
  static constexpr int id = 0xa;
};

struct B : Compound<B, A>
{
  static constexpr int id = 0xb;
};

template <typename T, typename Base> int get_id(const Compound<T, Base> &c)
{
  return c.get_id();
}


int test_a()
{
  A var;
  return get_id(var);
}

int test_b()
{
  B var;
  return get_id(var);
}

test_b doesn't compile with following error:

error: no matching function for call to 'get_id(B&)'
   return get_id(var);
                    ^
note: candidate: template<class T, class Base> int get_id(const Compound<T, Base>&)
 template <typename T, typename Base> int get_id(const Compound<T, Base> &c)
                                          ^
note:   template argument deduction/substitution failed:
note:   'const Compound<T, Base>' is an ambiguous base class of 'B'
   return get_id(var);

I understand why that is. B is derived and is convertible to both Compound<B, A> and Compound<A, Empty>

I'm wondering if it is possible to change (within context of C++14) Compound template and get_id() function such that it would return 0xa for A and 0xb for B and would work for arbitrarily long chains of inheritance.

I know that this can be easily solved with virtual function that is overridden in A and B, but I would like to avoid that if possible. Everywhere these types are used they are known and fixed at compile time so there shouldn't be a need to incur run-time overhead.

Upvotes: 0

Views: 56

Answers (2)

Barry
Barry

Reputation: 303097

Just keep it simple:

template <class T>
auto get_id(T const& c) -> decltype(c.get_id())
{
    return c.get_id();
}

You don't need c to be some Compound, you really just want it to have a get_id() member function.

Upvotes: 1

R Sahu
R Sahu

Reputation: 206607

It's not clear from your post why need to go the route of Compound in get_id. You can simply use:

template <typename T> int get_id(T const& c)
{
  return T::id;
}

Upvotes: 0

Related Questions