簡體   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