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 这里。

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

4

2 回答 2

3
typename PublishedTypes::published_t

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

分别会起作用。

它们是依赖于模板参数的类型(在模板实例化之前无法查找),因此需要由typename.

于 2013-10-04T10:05:45.993 回答
3

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

于 2013-10-04T10:06:51.603 回答