Canot access type from derived templated class

Hey guys,
i got the following code:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
template<size_t user_data_length>
class CParent
{
	struct SFoo
	{
		int foo_1;
		array<uint8_t, user_data_length> data;
	};

};


template<size_t user_data_length>
class CChild : CParent<user_data_length>
{
    SFoo foo_object = {};

};


However the compiler tells me that SFoo does not name a type. Why can i not access the derived class members?

Could you give me a hint?

Thx and happy new year :)

Last edited on
We need to tell the compiler that SFoo is a dependent name

1
2
3
4
5
6
template<size_t user_data_length>
class CChild : CParent<user_data_length>
{
    typename CParent<user_data_length>::SFoo foo_object = {};

};


More information: https://isocpp.org/wiki/faq/templates#nondependent-name-lookup-types
apart from that, SFoo is declared private
you're both correct. Thx that did work (and the link was very helpful :))

but what about functions that use the depended type
 
typename CParent<user_data_length>::SFoo Foo_Func(typename CParent<user_data_length>::SFoo& arg );




this does seem to work. But is there a way to avoid the typename in front of every type?

Can i somehow make use of the this operator to avoid a typename?
Is there a way to avoid the typename in front of every type?

Structure the code so that SFoo is not a dependent name. That is, move it to namespace scope:

1
2
3
4
5
6
7
8
9
10
template<size_t user_data_length>
struct SFoo {
	int foo_1;
	array<uint8_t, user_data_length> data;
};

template<size_t user_data_length>
class CParent {
  // Assume CParent uses user_data_length
};


Nested classes don't have significant special properties, so this is generally an easy refactor. Further, it makes it easier to ensure that SFoo doesn't depend on template parameters it shouldn't (i.e., according to the idea behind SCARY iterators - the recommendations as described in n2911: https://wg21.link/n2911 )
Last edited on
> but what about functions that use the depended type
> is there a way to avoid the typename in front of every type?

We can make the dependent names part of the current instantiation.
Then, we need to use the disambiguators only once, in the alias declaration.
See 'Current instantiantion': https://en.cppreference.com/w/cpp/language/dependent_name

For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
template < int N > struct A
{
    struct foo { /* ... */ };

    template < typename T > struct bar  { /* ... */ };
};

template < int N > struct B : A<N>
{
    // dependent names foo and bar are not part of the current instantiation:
    // typename and template disambiguators are required

    typename A<N>::foo my_foo ;
    typename A<N>::template bar<int> my_bar ;

    template < typename T >
    typename A<N>::foo fn( const typename A<N>::template bar<T>& ) { return {} ; }
};

template < std::size_t N > struct C : A<N>
{
    using foo = typename A<N>::foo ;
    template < typename T > using bar = typename A<N>::template bar<T> ;
    // dependent names foo and bar are made part of the current instantiation:
    // so, typename and template disambiguators are not required any more

    foo my_foo ;
    bar<int> my_bar ;

    template < typename T > foo fn( const bar<int>& ) { return {} ; }
};
hey thx for your helpfull answers.
I did some reading during the last days and decided to go with JLBorges Solution No 2. It works fine now. Thx for your quick help :)
Topic archived. No new replies allowed.