Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can I access the base class aliased types from the derived class?

In my development journey, today I found something that I do not understand why happens.

This should represent a generic a base unit in the SI:

template<Ratio r, Symbol s>
struct base_unit {
    using ratio = r;
    using symbol = s;
};

So, in my public interface, I am able to define a base dimension like this:

template <typename Dimension>
struct base_dimension {
    using dimension = Dimension;
};

And a concrete base unit like this:

struct mass : public base_dimension<mass> {};

So, I wanted to design a concept that checks for the presence of those aliases inside a unit, like for example, Kilogram:

struct Kilogram: public mass, public base_unit<Kilo, kg> {};

So I went ahead, and I wrote this concept, to constrain future implementors:

template <typename T>
concept Unit = requires {  
    typename T::base_dimension::dimension;
    typename T::base_unit::ratio;
    typename T::base_unit::symbol;
};

But, for my surprise, I am able to write this code:

template <typename T>
concept OtherUnitConcept = requires {  
    typename T::dimension;
    typename T::ratio;
    typename T::symbol;
};
static_assert(Unit<Kilogram>);
static_assert(OtherUnitConcept<Kilogram>);

Why I am able to directly request for those alias to T? The idea is that I am using those inheritance constructs as tag dispatching, and I supposed that I would always should take the full route, T::base_dimension::dimension , since T doesn't have in it's body definition a typename dimension, but base_dimension has one, and I looked surprised to be able to directly be able to found dimension in the construct T::dimension.

Here's a minimal working example

like image 557
Alex Vergara Avatar asked Oct 19 '25 02:10

Alex Vergara


1 Answers

TBH, your question should be Why can I access the base class aliased types from the derived class?

It's things about qualified name lookup. According to cppref,

If the lookup of the left hand side name comes up with a class/struct or union name, the name on the right hand side of :: is looked up in the scope of that class (and so may find a declaration of a member of that class or of its base), with the following exceptions

So, T::dimension can look up T::base_dimension::dimension if T::dimension is not found.

like image 182
Nimrod Avatar answered Oct 21 '25 15:10

Nimrod



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!