首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么不能使用CRTP的类型,却可以调用CRTP的方法?

为什么不能使用CRTP的类型,却可以调用CRTP的方法?
EN

Stack Overflow用户
提问于 2022-08-31 09:10:24
回答 2查看 75关注 0票数 -1

此代码只在调用CRTP的方法时编译和工作:

代码语言:javascript
复制
template <typename CRTP>
struct crtp
{
    // using type = typename CRTP::type; // will not compile
    void print() const
    {
        using type = typename CRTP::type; // compiles
        static_cast<const CRTP&>(*this).print();
    }
};

#include <iostream>

int main()
{
    struct foo : crtp<foo>
    {
        using type = int;
        void print() const {
            std::cout << "John Cena\n";
        };
    } f{};

    const crtp<foo>& c = f;
    c.print();

    return 0;
}

crtp<foo>的实例化中,foo是不完整的,但是它的方法是可以使用的。

然而,CRTP的类型不能使用CRTP外部功能的不完备性。

为什么允许将不完备性的检查推迟到调用类的函数,而不是在对象的暂存时进行?

当类主体中的using CRTP::type (未注释)出现时,将得到一个编译错误:

代码语言:javascript
复制
<source>:4:33: error: no type named 'type' in 'foo'
    using type = typename CRTP::type; // will not compile
                 ~~~~~~~~~~~~~~~^~~~
EN

回答 2

Stack Overflow用户

发布于 2022-08-31 09:38:43

注意,即使在类模板定义中编写成员函数定义,类模板实例化时也不会实例化。

foo在其基类crtp<foo>被完全定义后才能被定义,但是crtp<foo>定义中的类型别名要求知道foo的定义,这要求已经定义了crtp<foo>,需要foo,等等。

另一方面,成员函数直到它们的类被完全定义之后才会被编译,所以类型别名在那里是可以的。

(也就是说,实例化void crtp<foo>::print() const是因为它只发生在定义了foocrtp<foo>被实例化之后。)

将类模板定义与成员函数定义分离使两个阶段更加清晰:

代码语言:javascript
复制
template <typename CRTP>
struct crtp
{
    // Can't compile unless CRTP is defined at this point.
    using type = typename CRTP::type; 
    void print() const;
};


template <typename CRTP>
void crtp<CRTP>::print() const
{
    // Also can't compile unless CRTP is defined at this point, but
    // this is a later point than the class definition.
    using type = typename CRTP::type;
    static_cast<const CRTP&>(*this).print();
}
票数 2
EN

Stack Overflow用户

发布于 2022-08-31 09:27:04

在CRTP中,派生类是不完整的:

代码语言:javascript
复制
struct foo : crtp<foo> // foo incomplete here
{
    using type = int;
    void print() const {
        // foo complete here
        std::cout << "John Cena\n";
    }
}; // foo complete here

foo也是在void crtp<foo>::print() const中完成的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73553523

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档