模板和嵌套类型查找

时间:2013-10-04 10:00:00

标签: c++ templates inheritance

我有一个实现类似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。

我在名称查找规则中缺少什么?

2 个答案:

答案 0 :(得分:3)

typename PublishedTypes::published_t

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

分别会起作用。

它们是依赖于模板参数的类型(在模板实例化之前无法查找),因此需要由typename进行限定和预先添加。

答案 1 :(得分:3)

依赖于模板参数的类型需要以typename为前缀,如果是模板基类,则需要以父类的名称为前缀。但是,在最后一个示例中,该类不是模板,因此不需要这样,因为Cderived的类型查找在模板实例化之前不会延迟,因此常规查找规则适用。