2016-11-11 46 views
4

下面的代碼在GCC(4.9.3)和VC++(19.00.23506)中編譯得很好,但在Clang( 3.7.0)。Clang 3.7.0抱怨類不是字面的,因爲它不是一個聚合,也沒有constexpr構造函數

error: constexpr function's return type 'Foo' is not a literal type

note: 'Foo' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors

代碼:rextester運行

#include <iostream> 
#include <vector> 

struct Foo 
{ 
    std::vector<int> m_vec; 
    Foo(const int *foo, std::size_t size=0):m_vec(foo, foo+size) 
    {;} 
    //Foo(const std::initializer_list<int> &init):m_vec{init} 
    //{;} 
}; 


template <std::size_t N> 
constexpr Foo make_fooArray(const int (&a)[N]) noexcept 
{ 
    return {a,N}; 
} 


int main() 
{ 
    Foo f{ make_fooArray({1,2,3}) }; 

    for (auto i : f.m_vec) 
     std::cout<< i <<" "; 
    std::cout<<std::endl; 
} 

代碼:

GCC & VC

Clang

能否請你澄清這是否是一個編譯器錯誤或有我錯過了什麼? C++ 11標準是什麼意思?


這是另外一種情況,它在GCC和VC中編譯,但不在Clang中編譯。但是,如果你別名int []並明確使用它來指定initializer_list的類型,那麼它可以在所有編譯器中工作。

#include <iostream> 

template <typename T, std::size_t N> 
constexpr std::size_t sizeOf_fooArray(const T (&)[N]) noexcept 
{ 
    return N; 
} 

using intArray = int[]; //Added 

int main() 
{ 
    std::cout<< sizeOf_fooArray(intArray{16,20,53,87,54,7}) <<std::endl; 
} 

回答

8

所有的編譯器都是正確的。

使用函數模板,通常可能一個實例化符合constexpr函數的要求,但另一個實例化則不可以。通常情況下,這意味着constexpr對於那些不符合要求的實例化會被有效地忽略。例如:

template <typename T> constexpr T f(T v) { return v; } 

兩者f<int>f<std::string>實例是有效的,但f<std::string>不能在常量表達式被調用。

然而,作爲例外,這條規則,如果沒有任何可能導致一個滿足constexpr功能通常需要一個實例可能模板參數,該程序是形成不良的,沒有診斷需要。這意味着編譯器可以完全忽略這個規則,但它們同樣被允許將代碼診斷爲致命錯誤。

通常,不可能可靠地檢測違反此規則的情況,這就是爲什麼不需要診斷的原因。一些編譯器比其他編譯器更努力地仍然給出一些診斷。

所有這一切都在標準[dcl.constexpr] P6描述:

If the instantiated template specialization of a constexpr function template or member function of a class template would fail to satisfy the requirements for a constexpr function or constexpr constructor, that specialization is still a constexpr function or constexpr constructor, even though a call to such a function cannot appear in a constant expression. If no specialization of the template would satisfy the requirements for a constexpr function or constexpr constructor when considered as a non-template function or constructor, the template is ill-formed; no diagnostic required.

+0

這是輝煌!感覺就像是一個比編譯器錯誤更深的答案。我已經嘗試了你的解釋並看到了結果。 GCC中的相同代碼= http://rextester.com/OMFA48021,Clang = http://rextester.com/OYUZW55722 –

相關問題