2017-10-05 80 views
2

我有一個CRTP模板類在這裏:鐺VS GCC CRTP:constexpr變量不能有非文字類

template <typename S> 
class Base 
{ 
    public: 
    constexpr static S NOT_SET{0}; 
}; 

struct Derived : public Base<Derived> 
{ 
}; 

鏘(5.0.0)不接受這一點:

5 : <source>:5:24: error: constexpr variable cannot have non-literal type 'const Derived' 
    constexpr static S NOT_SET{0}; 
        ^
8 : <source>:8:25: note: in instantiation of template class 'Base<Derived>' requested here 
struct Derived : public Base<Derived> 
         ^
5 : <source>:5:24: note: incomplete type 'const Derived' is not a literal type 
    constexpr static S NOT_SET{0}; 
        ^
8 : <source>:8:8: note: definition of 'Derived' is not complete until the closing '}' 
struct Derived : public Base<Derived> 
    ^
1 error generated. 
Compiler exited with result code 1 

但海灣合作委員會(測試4.9.2和6.2)接受它就好了。

如何在叮噹中這樣做?

回答

2

Derived當您嘗試在類模板Base中使用它時不是一個完整的類型,因此您不能以這種方式實際使用它。這是因爲一個類型必須完整才能聲明該類型的變量。沒有辦法解決它。
綜上所述,類型在關閉}(以及與您的案例無關的其他例外情況,例如其成員函數內)完成。
這是標準的說什麼(working draft):

一類被認爲是在類說明符的關閉}完全定義的對象類型(或完整的類型)。
在類成員規範中,該類在函數體,默認參數,noexcept-說明符和默認成員初始化程序(包括嵌套類中的這些內容)中被認爲是完整的。
否則它在自己的類成員規範中被認爲是不完整的。

因此,鏗鏘是正確的,錯誤說或多或少相同。


正如在評論中提到的那樣,存在一種解決方法。只要派生類型是(可以說)constexpr constructible,您可以在基類中定義一個constexpr函數,該函數返回您的未設置版本(無論它的意思)。

+0

謝謝:但是,如果我試圖移植一個現有的代碼庫,它利用了GCC的這個「特性」來叮噹,你的建議是什麼? – Anton

+1

只要派生類型是constexpr可構造的,就可以在基類中定義一個constexpr函數,它返回它的_not set_版本(不管它是什麼意思)。它可以爲你工作嗎? – skypjack

+0

是的,這是個好主意。謝謝。我會接受你的回答,但是你認爲你也可以把你的評論放入答案中,作爲後代嗎? :-) – Anton