C ++`using`命令用于模板类中的类型别名

时间:2021-07-22 21:39:42

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:

1)在使用L之前添加typename:

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:

2)添加另一个using语句直接定位迭代器:

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.

但是,如果我还希望访问const_iterator等,那么就需要对我想要使用的每个迭代器都做同样的操作,而我宁愿不必定义一堆using语句。

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

那么,有没有办法编写using语句,然后允许我写:

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

Thanks!

2 个解决方案

#1


14  

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

typename必须在那里,但是你可以使用一些别名模板实用程序来避免每次都定义一个新的iter类型:

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;
};

#2


2  

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

不,没有。所有依赖类型必须以typename开头,或者通过带有typename的前言引入。

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

现在,您可以在某处使用declartion创建list_iter :

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

or even a meta-iter using statement:

甚至是使用声明的meta-iter:

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.

我在结构之外的using声明中“隐藏”了typename。

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

另外,99%的时间std :: list是错误的容器。

#1


14  

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

typename必须在那里,但是你可以使用一些别名模板实用程序来避免每次都定义一个新的iter类型:

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;
};

#2


2  

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

不,没有。所有依赖类型必须以typename开头,或者通过带有typename的前言引入。

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

现在,您可以在某处使用declartion创建list_iter :

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

or even a meta-iter using statement:

甚至是使用声明的meta-iter:

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.

我在结构之外的using声明中“隐藏”了typename。

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

另外,99%的时间std :: list是错误的容器。