Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ `using` command for type alias in template class

This seems like it should be really simple, but I've been playing and havn't found the solution I'm looking for yet, so here goes:

I have the following struct (simplified for illustrative purposes of course):

template<typename T>
struct test
    {
    using L = std::list<T>;
    L::iterator a;
    };

Now, this throws the error:

error: need 'typename' before 'test<T>::K::iterator' because 'test<T>::K' is a dependent scope

The two ways I have found of fixing it so far are both less than ideal:

1) add typename before any use of L:

template<typename T>
struct test
    {
    using L = std::list<T>;
    typename L::iterator a;
    };

I'd rather avoid the extra verbosity of this if possible.

2) add another using statement to target the iterator directly:

template<typename T>
struct test
    {
    using L = std::list<T>;
    using iter = typename L::iterator;
    iter a;
    };

But that would require having to do the same for every iterator I wanted to use, if I also wished to access the const_iterator etc etc, and I'd rather not have to define a bunch of using statements.

So, is there a way to write the using statement that then allows me to write:

 L::iterator a;
 L::const_iterator b;
 ...

Thanks!

like image 711
jsdw Avatar asked Dec 05 '22 11:12

jsdw


2 Answers

The typename must be there, but you can use a couple of alias template utilities to avoid defining a new iter type every time:

template<typename C>
using Iterator = typename C::iterator;

template<typename C>
using ConstIterator = typename C::const_iterator;

template<typename T>
struct test
{
    using L = std::list<T>;
    Iterator<L> i;
    ConstIterator<L> ci;
};
like image 102
Andy Prowl Avatar answered Dec 22 '22 00:12

Andy Prowl


Nope, there is not. All dependent types must either be prefaced with typename, or be brought in via a preface with typename.

Now, you could create a list_iter<T> using declartion somewhere:

template<typename T>
using list_iter = typename std::list<T>::iterator;

or even a meta-iter using statement:

template<template<typename>class container, typename T>
using iter = typename container<T>::iterator;
template<template<typename>class container, typename T>
using const_iter = typename container<T>::const_iterator;

which would let you do:

struct test {
  using L = std::list<T>;
  iter<std::list,T> a;
};

where I've "hidden" the typename in a using declaration outside of the struct.

As an aside, 99% of the time std::list is the wrong container.

like image 22
Yakk - Adam Nevraumont Avatar answered Dec 22 '22 00:12

Yakk - Adam Nevraumont