繁体   English   中英

将CRTP与static_assert一起使用时编译器错误

[英]Compiler error when using CRTP with static_assert

请考虑以下代码:

template<typename Derived>
struct Base {
    static constexpr int x_base = Derived::x_derived;
    //static_assert(x_base > 1, "Oops");
};

struct Derived : public Base<Derived> {
    static  constexpr int x_derived = 5 ;
};

Base<Derived> obj;

这在gcc上编译得很好但是如果我取消注释static_assert行,它就会抱怨

error: incomplete type 'Derived' used in nested name specifier
static constexpr int x_base = Derived::x_derived;

我从4.9到5.3的不同版本的gcc试了一下,我也得到了同样的错误(你可以尝试在godbolt 这里 )。 即使没有static_assert ,clang也拒绝编译它,并抱怨说

error: no member named 'x_derived' in 'Derived'
static constexpr int x_base = Derived::x_derived;

哪个编译器是正确的(如果有的话)? 有没有一种很好的方法来修复代码?

访问嵌套名称需要完成类,但Derived尚未完成:

template<typename Derived>
struct Base {
    static constexpr int x_base = Derived::x_derived;
                                  ^^^^^^^^^
};

所以代码是不正确的。

有一些解决方法。 首先,您可以单独传递值作为模板参数:

template <typename Derived, int x_derived>
struct Base {
    static constexpr int x_base = x_derived;
};

struct Derived : public Base<Derived, 5> { };

其次,如果可能(例如,您不需要x_derived来声明任何成员),您可以将值移动到函数中以延迟其实例化:

template<typename Derived>
struct Base {
    static constexpr int x_base() {
        static_assert(Derived::x_derived > 1, "Oops");
        return Derived::x_derived;
    }

};

struct Derived : public Base<Derived> {
    static constexpr int x_derived = 5;
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM