Template argument after scope resolution operator is not substituted

930 Views Asked by At

I'm trying to make a generic code that will cause a compile error if B is not an ancestor of D. What I came up with:

template<typename B, typename D>
struct assert_base_of {
    enum {value = sizeof(B::D)};
}

It doesn't work. When I 'call' it like this:

assert_base_of<A2,A1>::value;

I get the following error (g++ 4.8.2):

main.cpp:16:22: error: ‘D’ is not a member of ‘A2’

It looks like the template parameter D doesn't get substituted for A1. Can anyone explain and suggest a solution please?

1

There are 1 best solutions below

4
On

Inheritance does not enclose the derived class to the base class' scope so it makes no sense to use the scope resolution operator for that. The correct alternative (that also works with multiple inheritance) is to abuse the overload resolution rules:

#include <iostream>
#include <type_traits>

template<typename Base, typename Derived,
       bool = std::is_same<Base, Derived>::value>
struct is_base_of_impl
{

  typedef typename std::remove_cv<Base>::type     no_cv_base;      
  typedef typename std::remove_cv<Derived>::type  no_cv_derived;


  template<typename _Up>
  static std::true_type test(no_cv_derived&, _Up);
  static std::false_type test(no_cv_base&, int);

  //Black Magic
  struct converter
  {
   operator no_cv_derived&();
   operator no_cv_base&() const;
  };

  static const bool value = decltype(test(converter(), 0))::value;
};

template<typename Base, typename Derived>
struct is_base_of_impl<Base, Derived, true>
{ 
    static const bool value = std::is_same<Base, Derived>::value; 
};

template<typename Base, typename Derived>
struct is_base_of
: public std::integral_constant<bool,
               is_base_of_impl<Base, Derived>::value>
{ };


struct A {};
struct B1 : A {};
struct B2 : A {};
struct C : B1, B2 {};

int main()
{
    std::cout << is_base_of<A, B1>::value << "\n";
    std::cout << is_base_of<B1, C>::value << "\n";
    std::cout << is_base_of<A, C>::value << "\n";
    return 0;
}

For more information take a look into these links:

How does `is_base_of` work?

https://groups.google.com/d/msg/comp.lang.c++.moderated/xv4VlXq2omE/--WAroYkW2QJ