C++ Clang3.7.0抱怨类不是文字,因为它不是聚合,并且没有constexpr构造函数

C++ Clang3.7.0抱怨类不是文字,因为它不是聚合,并且没有constexpr构造函数,c++,c++11,c++14,constexpr,clang++,C++,C++11,C++14,Constexpr,Clang++,下面的代码在GCC(4.9.3)和VC++(19.00.23506)中编译得很好,但在Clang(3.7.0)中给出了这些错误 错误:constexpr函数的返回类型“Foo”不是文本类型 注意:“Foo”不是文字,因为它不是聚合,并且没有 除复制或移动构造函数以外的constexpr构造函数 代码: #包括 #包括 结构Foo { std::向量m_-vec; Foo(const int*Foo,std::size\u t size=0):m_vec(Foo,Foo+size) {;} //F

下面的代码在GCC(4.9.3)和VC++(19.00.23506)中编译得很好,但在Clang(3.7.0)中给出了这些错误

错误:constexpr函数的返回类型“Foo”不是文本类型

注意:“Foo”不是文字,因为它不是聚合,并且没有 除复制或移动构造函数以外的constexpr构造函数

代码:

#包括
#包括
结构Foo
{
std::向量m_-vec;
Foo(const int*Foo,std::size\u t size=0):m_vec(Foo,Foo+size)
{;}
//Foo(const std::初始值设定项\u list&init):m_vec{init}
//{;}
};
模板
constexpr Foo make_fooArray(const int&a)[N])noexcept
{
返回{a,N};
}
int main()
{
Foo f{make_Foo数组({1,2,3})};
用于(自动输入:f.m_vec)

所有的编译器都是正确的

对于函数模板,通常情况下,一个实例化可能满足
constepr
函数的要求,但另一个则不满足。通常,这意味着对于那些不满足要求的实例化,
constepr
有效地被忽略。例如:

template <typename T> constexpr T f(T v) { return v; }
template constexpr tf(tv){return v;}
f
f
实例化都有效,但不能在常量表达式中调用
f

但是,作为该规则的一个例外,如果没有任何可能的模板参数导致实例化满足
constexpr
函数的通常要求,则该程序是格式错误的,不需要诊断。这意味着编译器可以完全忽略此规则,但同样允许他们进行诊断将代码视为致命错误

一般来说,不可能可靠地检测到违反此规则的情况,这就是为什么不需要诊断。一些编译器比其他编译器更努力地提供一些诊断

[dcl.constexpr]p6中的标准中描述了所有这些:

如果
constepr
函数模板或类模板的成员函数的实例化模板专门化不能满足
constepr
函数或
constepr
构造函数的要求,则该专门化仍然是
constepr
函数或
constepr
构造函数,即使对此类函数的调用不能出现在常量表达式中。如果模板的专门化不能满足
constepr
函数或
constepr
构造函数(当被视为非模板函数或构造函数时)的要求,则模板格式错误;无需诊断


太棒了!感觉有一个比编译器错误更深刻的答案。我实际上已经尝试了你的解释并看到了结果。GCC=中的相同代码,叮当作响=
#include <iostream>

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

int main()
{
    std::cout<< sizeOf_fooArray({16,20,53,87,54,7}) <<std::endl;
}
#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;
}
template <typename T> constexpr T f(T v) { return v; }