Clang 3.7.0抱怨类不是文字的,因为它不是聚合的,并且没有constexpr构造函数 [英] Clang 3.7.0 complains of class not being literal because it is not an aggregate and has no constexpr constructors
问题描述
以下代码在GCC(4.9.3)和VC ++(19.00.23506)中可以很好地编译,但是在Clang(3.7.0)中会出现这些错误.
The following code compiles fine in GCC (4.9.3) and VC++ (19.00.23506) but gives these error in Clang (3.7.0).
错误:constexpr函数的返回类型'Foo'不是文字类型
error: constexpr function's return type 'Foo' is not a literal type
注意:'Foo'不是文字的,因为它不是集合,并且没有复制或移动构造函数以外的constexpr构造函数
note: 'Foo' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors
代码:
#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;
}
运行在代码上的代码:
能否请您说明这是编译器错误还是我错过了什么?C ++ 11标准怎么说?
Can you please clarify whether this is a compiler bug or have I missed something? What does the C++11 standard say?
还有另一种情况,它是在GCC和VC中编译的,而不是在Clang中编译的.
Here is one other case where it compiles in GCC and VC but not in Clang.
#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;
}
但是,如果您为int []加上别名并显式地使用它来指定initializer_list的类型,那么它就可以在所有编译器中使用.
However, if you alias the int[] and explicitly use it to specify the type of the initializer_list, then it works in all compilers.
#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;
}
推荐答案
所有编译器都是正确的.
All the compilers are right.
通常,使用函数模板,一个实例可以满足 constexpr
函数的要求,而另一实例则不能.通常,这意味着对于那些不符合要求的实例化, constexpr
有效地被静默忽略.示例:
With function templates, in general, it's possible that one instantiation meets the requirements for a constexpr
function, but another doesn't. Normally, that means constexpr
effectively gets ignored silently for those instantiations that don't meet the requirements. Example:
template <typename T> constexpr T f(T v) { return v; }
f< int>
和 f< std :: string>
实例化均有效,但 f< std :: string>
不能在常量表达式中调用.
Both the f<int>
and f<std::string>
instantiations are valid, but f<std::string>
cannot be called in a constant expression.
但是,作为该规则的例外,如果没有任何个可能的模板参数可以导致实例化满足 constexpr
函数的通常要求,该程序格式错误,无需诊断.这意味着编译器可以自由地完全忽略该规则,但是同样可以允许他们将代码诊断为致命错误.
However, as an exception to that rule, if there isn't any possible template argument that could lead to an instantiation that meets the usual requirements for constexpr
functions, the program is ill-formed, no diagnostic required. This means compilers are at liberty to ignore this rule entirely, but they are equally allowed to diagnose the code as a fatal error.
通常,不可能可靠地检测到违反此规则的情况,这就是为什么不需要诊断的原因.有些编译器比其他编译器更努力地尝试以给出诊断信息.
In general, it's not possible to reliably detect violations of this rule, that's why no diagnostic is required. Some compilers try harder than others to still give some diagnostics.
所有这些都在[dcl.constexpr] p6的标准中进行了描述:
All of this is described in the standard in [dcl.constexpr]p6:
如果
constexpr
函数模板或类模板的成员函数的实例化模板特化将无法满足constexpr
函数或constexpr
构造函数,即使对这样的函数的调用不能出现在常量表达式中,该专业化仍然是constexpr
函数或constexpr
构造函数.如果模板的特殊化不能满足constexpr
函数或constexpr
构造函数的要求(当它们被视为非模板函数或构造函数时),则该模板格式错误;无需诊断.
If the instantiated template specialization of a
constexpr
function template or member function of a class template would fail to satisfy the requirements for aconstexpr
function orconstexpr
constructor, that specialization is still aconstexpr
function orconstexpr
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 aconstexpr
function orconstexpr
constructor when considered as a non-template function or constructor, the template is ill-formed; no diagnostic required.
这篇关于Clang 3.7.0抱怨类不是文字的,因为它不是聚合的,并且没有constexpr构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!