2016-10-04 71 views
3

在下面的代码片断:指依赖类型名

#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(){} 

标记行是难看,并且还包含重复的信息(如果基类参数的变化的类型,这条线也必须被改变)。但是有必要重复这样的声明,否则代码不会编译。另外,我想避免做一个全局typedef声明...

有没有解决方案来引用在模板相关的基类中定义的类型?

回答

4

您可以传递一个容器类型为模板参数:

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

附:同样的事情可以在基类中完成。

+0

问题是,这样看来,人们可以随意选择C的值,而在我的情况下,如果用户更改C,代码可能会以一些不可预见的方式破坏。 C是一个实现细节。 –

+0

@EmanuelePaolini也许'typedef std :: map > Map;'在声明'struct Derived'之前,然后简单地'Base '而不是在两种情况下? –

+0

@ W.F。这将是一个全局的typedef,其实现细节也是我想避免的。 –

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■找被替换通过使用声明。

1

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

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

如果你恨了一遍又一遍写了整个事情,然后用一个新的成员别名:

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