引用依赖类型名

时间:2016-10-04 20:35:54

标签: c++ templates using

在以下代码段中:

#include <map>

template<class T>
struct Base {
  typedef T U;
};

template<class T>
struct Derived: public Base<std::map<int,std::map<int,T>>> {
  typedef typename Base<std::map<int,std::map<int,T>>>::U U; // ugly!

  void F(U u) {};
};

int main(){}

标记的行很难看并且还包含重复的信息(如果Base类参数的类型发生更改,则此行也必须更改)。但是必须有这样的重复声明,否则代码不会编译。另外,我想避免制作全局typedef声明......

是否有解决方案来引用模板依赖基类中定义的类型?

3 个答案:

答案 0 :(得分:4)

您可以将容器类型作为模板参数传递:

template<class T, class C = std::map<int,std::map<int,T>>>
struct Derived: public Base<C> {
  typedef typename Base<C>::U U;
//...
};

P.S。同样的事情可以在基类中完成。

答案 1 :(得分:3)

如果你至少可以使用C ++ 11,你可以结合一个函数声明(这里不需要定义)和using声明,如下所示:

#include <map>
#include<utility>

template<class T>
struct Base {
  using U = T;
};

template<typename T>
typename Base<T>::U f(Base<T>);

template<typename T>
using BType = decltype(f(std::declval<T>()));

template<class T>
struct Derived: public Base<std::map<int,std::map<int,T>>> {
  using U = BType<Derived>;
  void F(U u) {};
};

int main(){}

另请注意,typedef也已被使用声明替换。

答案 2 :(得分:1)

问题是非限定名称查找不会查看依赖基类。因此,只需限定名称并告诉编译器U将成为Derived的成员:

void F(typename Derived::U u) {}

如果你不喜欢一遍又一遍地写出整件事,那就使用一个新的成员别名:

using DU = typename Derived::U; // or typedef equivalent