[英]Constexpr static member function usage
請考慮以下示例代碼:
#include <array>
struct MyClass
{
size_t value = 0;
constexpr static size_t size() noexcept
{
return 3;
}
};
template <size_t N>
void DoIt()
{
MyClass h;
std::array<int, h.size()> arr;
}
int main()
{
DoIt<1>();
}
當我嘗試使用GCC 7.3.0編譯它時,我得到一個關於h在非constexpr上下文中不可用的錯誤:
cexpr.cpp: In function ‘void DoIt()’:
cexpr.cpp:17:26: error: the value of ‘h’ is not usable in a constant expression
std::array<int, h.size()> arr;
^
cexpr.cpp:16:11: note: ‘h’ was not declared ‘constexpr’
MyClass h;
^
cexpr.cpp:17:27: error: the value of ‘h’ is not usable in a constant expression
std::array<int, h.size()> arr;
^
cexpr.cpp:16:11: note: ‘h’ was not declared ‘constexpr’
MyClass h;
^
但是,當我嘗試在Clang 6.0.0中編譯完全相同的代碼時,它編譯時沒有任何錯誤。 另外,當我修改代碼不在模板化的DoIt()
函數中時,GCC編譯就好了:
#include <array>
struct MyClass
{
size_t value = 0;
constexpr static size_t size() noexcept
{
return 3;
}
};
int main()
{
MyClass h;
// this compiles just fine in Clang and GCC
std::array<int, h.size()> arr;
}
我已經知道如何修復第一個代碼,所以它使用decltype
在GCC上編譯,但我很想知道為什么第一段代碼不能用GCC編譯? 這只是GCC中的一個錯誤,還是我對使用constexpr靜態成員函數有些不了解?
對我來說看起來像個錯誤。
表達式h.size()
的類型和含義由[expr.ref]
“類成員訪問”定義:
[expr.post]/3
將postfix-expression.id-expression縮寫為
E1.E2
,E1
稱為對象表達式。 [...]
和
[expr.post]/6.3.1
如果
E2
是(可能是重載的)成員函數,則使用函數重載E1.E2
來確定E1.E2
是指靜態成員函數還是非靜態成員函數。
- (6.3.1)如果它引用靜態成員函數並且
E2
的類型是“參數類型列表返回T
函數”,則E1.E2
是左值; 表達式指定靜態成員函數 。E1.E2
的類型與E2
類型相同,即“參數類型列表返回T
函數”。
這意味着h.size
與::MyClass::size
具有相同的類型,並且無論h
是constexpr
還是not , 都會被評估。
然后, h.size()
調用constexpr
函數,並且是[expr.const]/4
的核心常量表達式 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.