簡體   English   中英

gcc和clang對constexpr功能不一致

[英]gcc and clang disagree over constexpr function

從生成器函數編寫一個簡單的編譯時std::array factory,我偶然發現:clang ++ 3.5.1和g ++ 4.9.2不同意函數是否是constexpr

代碼(這是c ++ 14!):

#include <array>
#include <utility>

    template <class T, std::size_t N, class GenType, std::size_t... I> 
    constexpr std::array<T, N>
make_array_impl (GenType gen, std::index_sequence <I...>) 
{
    return {{ gen (I)... }};
}

    template <class T, std::size_t N, class GenType> 
    constexpr std::array<T, N>
make_array (GenType gen)
{
    return make_array_impl <T, N> (
            gen, 
            std::make_index_sequence <N> {}
    );
}

    constexpr int
generator_const (std::size_t /* index */)
{
    return 1;
}

    constexpr auto
a = make_array <int, 3> (generator_const);

static_assert (a.size () == 3, "");
static_assert (a[0] == 1, "");
static_assert (a[1] == 1, "");
static_assert (a[2] == 1, "");

int main () {}

用g ++編譯:

migou ~ % g++ -std=c++14 ex.cpp  
ex.cpp:28:41:   in constexpr expansion of ‘make_array<int, 3ul, int (*)(long unsigned int)>(generator_const)’
ex.cpp:18:5:   in constexpr expansion of ‘make_array_impl<int, 3ul, int (*)(long unsigned int), {0ul, 1ul, 2ul}>(gen, (std::make_index_sequence<3ul>{}, std::make_index_sequence<3ul>()))’
ex.cpp:8:21: error: expression ‘generator_const’ does not designate a constexpr function
 return {{ gen (I)... }};

使用clang ++它編譯得很好。 我可以繼續考慮這個有效的g ++ 14(因此g ++有問題嗎?)?

正如@Casey在評論中正確指出的那樣, std::array或其他聚合的隱式構造函數的constexpr -ness沒有任何模糊性:

12.1構造函數[class.ctor]

5當使用odr-used(3.2)來創建其類類型(1.8)的對象或在第一次聲明后顯式默認為默認構造函數時,默認構造函數是默認的並且未定義為已刪除。 隱式定義的默認構造函數執行該類的初始化集,該初始化集將由該用戶編寫的默認構造函數執行,該類沒有ctor-initializer(12.6.2)和空復合語句。 如果該用戶編寫的默認構造函數不正確,則程序格式錯誤。 如果該用戶編寫的默認構造函數滿足constexpr構造函數(7.1.5)的要求,則隱式定義的默認構造函數為constexpr 在隱式定義類的默認默認構造函數之前,應隱式定義其基類及其非靜態數據成員的所有非用戶提供的默認構造函數。 [注意:隱式聲明的默認構造函數具有異常規范(15.4)。 明確默認的定義可能有隱式的例外規范,見8.4。 - 尾注]

這已在最新的gcc HEAD 5.0.0 20150217中修復,請參閱此實例 ,並且已經在Clang工作了近一年半(自3.4版本IIRC以來,請參閱此問答 )。

這有點模糊。 禁止在C ++ 14中使用constexpr的規則(N3797,5.19 / 2 bullet 2)

調用constexpr構造函數以外的函數,用於文字類,constexpr函數或簡單析構函數的隱式調用

constexpr不是類型的一部分,因此傳遞給make_array_impl的函數指針不是constexpr函數。 另一方面,它的是constexpr函數,由於這是constexpr評估,編譯器必須知道。

但是,Clang支持該代碼,並且GCC 4.9並未聲稱與輕松的constexpr函數一致,因此在這種情況下我會信任Clang。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM