Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is 'typedef' automatically inherited in C++ class?

Tags:

c++

c++11

I used to believe that 'typedef' is not automatically inherited. But the code snap below suggests something different.

#include <iostream>
#include <type_traits>

struct A
{
    typedef int X;
};

struct A_ 
{
    typedef char X;
};

struct B : A {};
struct B_ : A, A_ {};

template< typename ... Ts >
using void_t = void;

template< typename T, typename = void >
struct has_typedef_X : std::false_type {};

template< typename T >
struct has_typedef_X< T, void_t<typename T::X> > : std::true_type {};

int main()
{
    std::cout << std::boolalpha;
    std::cout << has_typedef_X<A>::value << std::endl;
    std::cout << has_typedef_X<A_>::value << std::endl;
    std::cout << has_typedef_X<B>::value << std::endl;
    std::cout << has_typedef_X<B_>::value << std::endl;
    return 0;
}

The output is 'true true true false'. But in my point of view, 'has_typedef_X<B>::value' giving 'true' implies that in struct B, X is 'typedef'ed.

So if anyone can please explain this problem or correct me?

A online version is available at http://melpon.org/wandbox/permlink/iwZ6eZ3PoBPgyFBj [URL corrected]

like image 513
Feng Wang Avatar asked May 13 '16 09:05

Feng Wang


3 Answers

Nested type names (i.e. member types) of parents are visible in the scope of a derived class and accessible as long as the access specifier of is not private. If there are multiple types with the same name from different base classes, then the unqualified name is ambiguous.

The most relevant standard quotes that I found regarding this are:

[class.nested.type] §1

Type names obey exactly the same scope rules as other names. [...]

[class.member.lookup] §9

[ Note: A static member, a nested type or an enumerator defined in a base class T can unambiguously be found even if an object has more than one base class subobject of type T. [...]

In fact, an example of using this is the standard which specifies that the iterators of standard containers inherit std::iterator template, which contains nothing but nested type names. The whole point of the inheritance is to get these nested type names to the iterator. (This example will become outdated in the next standard version (c++17), where std::iterator is proposed not to be used anymore.)

like image 152
eerorika Avatar answered Oct 03 '22 19:10

eerorika


X is in scope for both B and B_, the issue with B_ is that B_::X is ambiguous, so template deduction fails for the truthy has_typedef leaving the false one as the only match.

like image 32
user657267 Avatar answered Oct 03 '22 19:10

user657267


Since the name X is ambiguous due to being defined in two base classes, this causes template deduction to fail for B_ in has_typedef.

Your belief that typedefs are not inherited might have come from some C++ specialties during unqualified name lookup, where base classes are not considered. See Propagating 'typedef' from based to derived class for 'template'

like image 21
Nick Nougat Avatar answered Oct 03 '22 18:10

Nick Nougat