2013-10-04 130 views
2

我有一個模板類層次結構實現類似模式的CRTP。我不明白爲什麼名稱查找在標有錯誤的行中失敗,並且在標有「此處沒有錯誤」的行中成功。模板和嵌套類型查找

class CPublishedTypes 
{ 
    public: 
    typedef int published_t; 
}; 

template<class Derived, class PublishedTypes> class Cbase: public PublishedTypes 
{ 
    public: 
     Cbase():ibase_(42){} 
    private: 
     published_t ibase_; //error: 'published_t' does not name a type  
}; 

template<class Derived> class Cmiddle : public Cbase<Derived, CPublishedTypes> 
{  
    public: 
     Cmiddle():imiddle_(42){} 
    private: 
     published_t imiddle_; //error: 'published_t' does not name a type  
}; 

class Cderived : public Cmiddle<Cderived> 
{ 
    public: 
     Cderived():iderived_(42){} 
    private: 
     published_t iderived_; // No errors here 
}; 

int main(int argc, char *argv[]) 
{ 
    Cderived derived; 
    return 0; 
} 

使用'typename'沒有幫助。

的C++ FAQ描述了相似但不相同的問題在這裏:http://www.parashift.com/c++-faq/nondependent-name-lookup-types.html

CBase的從PublishedTypes,這是一個模板參數公開繼承,但它不是一個模板。所以我不明白爲什麼CPublishedTypes :: published_t是無法訪問的。

Cderived從Cmiddle繼承,Cmiddle繼承自Cbase。所以我不明白爲什麼我不需要一個類型名來訪問CPublishedTypes :: published_t這裏。

我在名稱查找規則中缺少什麼?

+0

@templaterex:不完全重複。 Hassan Syed的例子看起來像FAQ條目:他從模板基類繼承。我是從一個簡單的非模板類繼承的,它恰好是一個模板參數。 –

回答

3
typename PublishedTypes::published_t 

typename Cbase<Derived, CPublishedTypes>::published_t 
// or simpler 
typename Cmiddle::published_t 

分別將工作。

它們是取決於模板參數的類型(並且在模板被實例化之前無法查找),因此需要通過typename進行驗證和預置。

3

依賴於模板參數的類型需要以typename爲前綴,對於模板基類,則是父類的名稱。然而,在最後一個示例中,該類不是模板,因此這不是必需的,因爲Cderived的類型查找在模板實例化之前不會延遲,因此應用常規查找規則。