我有一个实现类似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公开继承,这是一个模板参数,但它不是模板 class 。所以我不明白为什么CPublishedTypes :: published_t不可访问。
Cderived继承自Cmiddle,而Cmiddle又继承自Cbase。所以我不明白为什么我不需要一个typename来访问CPublishedTypes :: published_t。
我在名称查找规则中缺少什么?
答案 0 :(得分:3)
typename PublishedTypes::published_t
和
typename Cbase<Derived, CPublishedTypes>::published_t
// or simpler
typename Cmiddle::published_t
分别会起作用。
它们是依赖于模板参数的类型(在模板实例化之前无法查找),因此需要由typename
进行限定和预先添加。
答案 1 :(得分:3)
依赖于模板参数的类型需要以typename
为前缀,如果是模板基类,则需要以父类的名称为前缀。但是,在最后一个示例中,该类不是模板,因此不需要这样,因为Cderived
的类型查找在模板实例化之前不会延迟,因此常规查找规则适用。