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

查看:92
本文介绍了Clang 3.7.0抱怨类不是文字的,因为它不是聚合的,并且没有constexpr构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码在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;
}

运行在代码上的代码:

GCC&VC

C语

能否请您说明这是编译器错误还是我错过了什么?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 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.

这篇关于Clang 3.7.0抱怨类不是文字的,因为它不是聚合的,并且没有constexpr构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆