2016-10-04 70 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