【问题标题】:C++ constexpr function template compiles with non-literal and non-aggregate types. Is this a bug with gcc? [duplicate]C++ constexpr 函数模板使用非文字和非聚合类型进行编译。这是 gcc 的错误吗? [复制]
【发布时间】:2020-11-20 18:35:52
【问题描述】:

考虑以下代码:

#include <iostream>
#include <cstdlib>

struct NonAggregate
{
    // Non-aggregate due to user defined constructor
    // It is also not constexpr
    explicit NonAggregate(int i) : val_(i) {}
    int val_;
};

template <typename T = int>
constexpr NonAggregate GetNonAggregate(NonAggregate foo)
{
    return foo;
}

int main() 
{
    // Let us pass a random value to the constructor that can only be known at runtime just in case
    std::cout << GetNonAggregate(NonAggregate(std::rand())).val_ << std::endl;
    return 0;
}

此代码使用 gcc 10.2,as seen here in godbolt 编译。这段代码不能用 clang 编译:

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

但是,如果我们只是从 GetNonAggregate() constexpr 函数中删除模板:

constexpr NonAggregate GetNonAggregate(NonAggregate foo)
{
    return foo;
}

然后代码无法使用 clang 和 gcc 编译。我在这里有什么遗漏吗?此代码不是有效的 C++,但代码库的某些部分依赖于 gcc 的这种行为,当我们尝试使用 clang 时突然无法编译。

我还没有用 msvc 编译器测试过这段代码,我会在测试时更新这个问题。

【问题讨论】:

  • 你指的是godbolt上的msvc有什么问题?另外,如果您不关心 msvc 的作用,您可以删除最后一句。
  • @cigien 当我尝试在 Godbolt 上使用 msvc 编译代码示例时,我得到“内部服务错误”。我在 Godbolt 上从来没有遇到过这个问题,msvc 总是为我工作,所以我认为这是 Godbolt 本身的临时错误。
  • 嗯,我不确定,但鉴于 clang 和 gcc 在代码上存在分歧,这可能是 msvc 编译器错误。无论如何,您应该在最后一句中提及该特定信息。
  • 直到msvc版本在godbolt上编译成功我会修改那句话。

标签: c++ language-lawyer constexpr function-templates


【解决方案1】:

根据temp#res.general-8.1

无法为模板或 constexpr if 语句的子语句生成有效的特化,并且模板未实例化,或者

根据dcl.constexpr#7

如果 constexpr 函数模板或类模板的成员函数的实例化模板特化无法满足 constexpr 函数的要求,则该特化仍然是 constexpr 函数,即使对此类函数的调用不能出现在一个常量表达式。如果模板的特殊化在被视为非模板函数时不能满足 constexpr 函数的要求,则该模板是非良构的,不需要诊断。

确实是为了

template <typename T = int>
constexpr NonAggregate GetNonAggregate(NonAggregate foo)
{
    return foo;
}

没有T 可以使函数 constexpr。所以代码是格式错误的 NDR。

Clang 可以很好地进行诊断。

【讨论】:

  • 感谢您的回复,看来我应该向 gcc 提交错误报告。
  • 本身。它不是 gcc 的错误,如 NDR。但这将是一个很好的改进。
  • 此报价不适用于此处。如果模板没有被实例化,它说它是 IFNDR,但是 OP 正在实例化它。
  • 没错,示例中实例化了GetNonAggregate&lt;int&gt;。此外,标准中引用的语句是指在此处不存在的 constexpr-if 语句的上下文中的实例化?模板应该不会影响该程序的编译结果(在任何一种情况下都应该失败),但确实如此。
  • @cigien:找到dcl.constexpr#7 而不是temp#res.general-8.1。 :)
猜你喜欢
  • 2022-08-14
  • 2018-07-10
  • 1970-01-01
  • 2020-07-05
  • 2014-05-16
  • 2019-05-06
  • 2018-06-17
  • 2017-09-17
  • 1970-01-01
相关资源
最近更新 更多