左值ref对象上的Constexpr成员函数:Clang和gcc不同意 [英] Constexpr member function on l-value ref object: Clang and gcc disagree

查看:66
本文介绍了左值ref对象上的Constexpr成员函数:Clang和gcc不同意的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当类具有constexpr成员函数并且正在constexpr上下文中的l值对象上对该成员函数进行求值时,clang和gcc会不同意结果是否为constexpr值.为什么?是否有既不需要默认可构造性又不需要复制可构造性的解决方法?

When a class has a constexpr member function and that member function is being evaluated on an l-value object in a constexpr context, clang and gcc disagree whether the result is a constexpr value. Why? Is there a workaround that needs neither default-constructability nor copy-constructability?

当对象通过值传递时,两个编译器均成功编译.

When the object is passed by value, both compilers succeed compiling.

Clang版本的trunk,8、7: static_assert表达式不是整数常量表达式

Clang versions trunk, 8, 7: static_assert expression is not an integral constant expression

Gcc版本trunk,8.1、7.4:编译没有错误

Gcc versions trunk, 8.1, 7.4: compiles with no error

#include <array>

using A = std::array<int, 10>;

void foo(const A& a){
    // clang: static_assert expression is not an integral constant expression
    static_assert(a.size() > 0, "");
}


void foo2(A a){
    // this compiles on both clang and gcc
    static_assert(a.size() > 0, "");
}

// Some custom code with the same symptom:
class B{
  public:
    constexpr int size()const{
        return 42;
    }
};

void foo3(const B& b){
    // clang: static_assert expression is not an integral constant expression
    static_assert(b.size() > 0, "");
}


void foo4(B b){
    // this compiles on both clang and gcc
    static_assert(b.size() > 0, "");
}

https://godbolt.org/z/9vmyli

注意事项的解决方法:

void foo5(const B& b){
    // This works in clang, if the default constructor is defined
    static_assert(B().size() > 0, "");
}

void foo6(const B& b){
    // This works in clang, if the copy constructor is defined
    [](B b){static_assert(b.size() > 0, "");}(b);
}

推荐答案

核心常数表示:

核心常量表达式是其求值将为不评估以下任何一项:

A core constant expression is any expression whose evaluation would not evaluate any one of the following:

...

  1. 一个 id-expression 引用引用类型的变量或数据成员,除非已使用常量表达式对其进行了初始化或其生命期始于对该表达式的评估
  1. an id-expression referring to a variable or a data member of reference type, unless it was initialized with a constant expression or its lifetime began within the evaluation of this expression

...

因此,不允许您使用参考 const A&一个在这里.

So you are not allowed to have reference const A& a here.

例如,以下代码片段可以很好地编译:

As an example, the following snippet compiles fine:

using A = std::array<int, 10>;

constexpr A arr = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
constexpr const A& arr_ref = arr;   // OK: arr_ref is initialized with a constant expr

static_assert(arr.size() > 0, "");
static_assert(arr_ref.size() > 0, "");

这篇关于左值ref对象上的Constexpr成员函数:Clang和gcc不同意的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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