Propagating 'Typedef' from Based to Derived Class For 'Template'

Propagating 'typedef' from based to derived class for 'template'

I believe that this question is duplicate, but I cannot find it now. C++ Standard says that you should fully qualify name according to 14.6.2/3:

In the definition of a class template or a member of a class template, if a base class of the class template depends on a template-parameter, the base class scope is not examined during unqualified name lookup either at the point of definition of the class template or member or during an instantiation of the class template or member.

UPD: I found duplicate finally: here it is.

Unable to import of typedefs from template base class

I think the confusion arises from the way A is used as a base class. If a class template derives from a class template with a template argument, you have to fully qualify the base class name. But if a class derives from a class template specialization, you can use the base class name without a template argument list.

template<typename T>
struct A {
using t = T;
};

template<typename T>
struct B : A<T> {
using typename A<T>::t; // Full qualification needed -> mandatory argument list
};

struct C : A<int> {
using typename A::t; // Injected class name -> optional argument list
};

Live on Coliru

Also, note that t is available in C directly, without any using declaration or typedef. I may still be useful, for example if C inherits from A<int> privately, but you want t to be available publicly in C (in the example, C inherits publicly by default because it is a struct).

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

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.)

Why does the child class not see the parent's typedef struct in C++?

This

typedef struct {
S x;
T y;
}

is ill-formed. typedef needs a type and an "alias" to name that type. What you probably need is

template<typename S, typename T> 
class A {
public:
struct Datum { S x; T y; };
};

without the typedef, which is not necessary at all here. Then, you need to qualify the Datum name properly, as typename A<Q,Q>::Datum:

#include "A.h"
template<typename Q>
class B : public A<Q, Q> {
public:
void output(const typename A<Q,Q>::Datum& dat);
};

C++ template class inherit

The issue here is that the base class LooperQueue is a dependent base class, which depends on the template parameter Tp and Sequence, then its complete type can't be determined without knowing the template arguments. Standard C++ says that nondependent names (like size_type, reference and value_type) won't be looked up in dependent base classes.

To correct the code, it suffices to make the names qualified by the base class name; then these names can be looked up only at the time of instantiation, and at that time the exact base specialization that must be explored will be known. e.g.

template<typename _Tp, typename _Sequence = std::deque<_Tp> >
class StdQueue : public LooperQueue<_Tp, _Sequence> {
public:
typename LooperQueue<_Tp, _Sequence>::::size_type size() override;
typename LooperQueue<_Tp, _Sequence>::reference front() override;
void pop() override;
void push(const typename LooperQueue<_Tp, _Sequence>::value_type &__x) override;
private:
std::queue<_Tp, _Sequence> mQueue;
};

Inheritting type aliases in template classes

So to sum up the back and forth me and @N.Shead had in the comments, supported by these links on why you can't do it better:

Propagating 'typedef' from based to derived class for 'template'

Inheritance and templates in C++ - why are inherited members invisible?

This seems to be the best we can do:

#include <iostream>

template<typename T /* And a bunch more */>
struct LibStruct {
using Scalar = T;
// ... and a lot more aliases
};

#define LIBSTRUCT_TYPES(base) \
using Scalar = typename base::Scalar; \
// ... and a lot more

template<typename T>
struct ClientStuctA : LibStruct<T> {
LIBSTRUCT_TYPES(LibStruct<T>)

Scalar moreData;
// OtherTypes moreDefinitions();

Scalar func1() { return Scalar(2) * 3; }
Scalar func2();
};

template<typename T>
typename ClientStuctA<T>::Scalar ClientStuctA<T>::func2() {
return 5;
}

int main() {
std::cout << ClientStuctA<int>().func1() << std::endl;
std::cout << ClientStuctA<int>().func2() << std::endl;
return 0;
}

Specifying one of base class template parameters by derived class template parameter. How to use base class's using declarations

myflt_t defined in class a is not visible in class b as explained here: https://eli.thegreenplace.net/2012/02/06/dependent-name-lookup-for-c-templates

You can bring myflt_t into class b by without the explicit re-declaration:

using typename base_t::myfl_t

typedef inheritance from a pure abstract base

you should do

typedef typename TemplateMethod<X>::system_t system_t;

to "inherit" typedef. typedef is not automatically inherited (if compiler is compliant).

if you look through stack overflow, there will be duplicate of this question somewhere.

avoid duplicated code : typedef/using a template class that has default parameter (C++14)

You can make use of a parameter pack:

template <class T1, class... T3>
using F = E<T1, C, T3...>;

... to directly forward zero or one argument to E.



Related Topics



Leave a reply



Submit