首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >通过const引用传递constexpr对象的原因是可行的,但根据值却不能编译

通过const引用传递constexpr对象的原因是可行的,但根据值却不能编译
EN

Stack Overflow用户
提问于 2015-05-11 16:06:08
回答 2查看 954关注 0票数 7

下面的代码基本上是在编译时将一个std::integer_sequence<>映射为一个std::array<>

代码语言:javascript
复制
#include <iostream>
#include <utility>
#include <array>

template<int...Is>
constexpr auto make_array(const std::integer_sequence<int, Is...>& param) // this works */
// constexpr auto make_array(std::integer_sequence<int, Is...> param) // doesn't compile
{
    return std::array<int, sizeof...(Is)> {Is...};
}

int main()
{
    constexpr std::integer_sequence<int, 1,2,3,4> iseq;

    // If I pass by value, error: the value of 'iseq' is not usable in a constant expression
    constexpr auto arr = make_array(iseq);  

    for(auto elem: arr)
        std::cout << elem << " ";
}

每当make_array采用const-reference的参数时,代码就能正常工作。每当我尝试按值传递它(如在注释行中)时,它就会产生一个错误:

错误:“iseq”的值在常量表达式中不可用 make_array(iseq);

为什么会这样呢?参数iseq当然是一个常量表达式,为什么我不能将它传递给make_array

例如,下面的代码在按值传递时按预期工作:

代码语言:javascript
复制
#include <iostream>
#include <utility>

struct Foo
{
    int _m;
    constexpr Foo(int m): _m(m){};
};

constexpr Foo factory_foo(int m)
{
    return Foo{m};
}

constexpr Foo copy_foo(Foo foo)
{
    return foo;
}

int main()
{
    constexpr Foo cxfoo = factory_foo(42);
    constexpr Foo cpfoo = copy_foo(cxfoo);
}

编辑

我正在使用来自macport的g++5.1。使用clang++ 3.5,即使是使用g++编译的代码(使用const引用),也会收到错误消息:

错误:默认初始化类型为“const std::integer_sequence”的对象需要用户提供的默认构造函数。

因此,我想缺少一个用户提供的默认构造函数有一些问题,但在这一点上,我并不真正理解发生了什么。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-05-11 16:19:24

您在iseq上缺少了一个初始化器。你必须加上:

代码语言:javascript
复制
constexpr std::integer_sequence<int, 1,2,3,4> iseq{};
                                                  ^^

来自dcl.constexpr

对象声明中使用的constexpr说明符将对象声明为const。这样的对象应该具有文字类型,将被初始化为。如果它是由构造函数调用初始化的,则该调用应该是一个常量表达式(5.20)。否则,或者如果在引用声明中使用constexpr说明符,则其初始化程序中出现的每个完整表达式都将是一个常量表达式。[注意:用于转换初始化表达式的每个隐式转换和用于初始化的每个构造函数调用都是这种完整表达式的一部分。-end注记] [例子: 结构像素{ int x,y;};constexpr像素ur ={ 1294,1024 };// OK不变像素原点;//错误:初始化器缺失 -end示例]

此外,正如哥伦布在他的commentanswer中所指出的,简单地初始化是不够的。还需要一个用户提供的构造函数,如dcl.init所示。

如果程序调用const限定类型T的对象的默认初始化,则T应该是具有T默认构造函数的类类型。

让最相关的部分(dcl.constexpr)对constepxr对象声明的需求进行不完整的描述有点奇怪。

票数 5
EN

Stack Overflow用户

发布于 2015-05-11 16:19:10

如果程序调用const限定类型T的对象的默认初始化,则T应该是具有用户提供的默认构造函数的类类型。

但是,integer_sequence没有任何用户提供的构造函数,而constexpr为变量提供了const,因此如果没有初始化器,就无法定义该类型的constexpr对象。

添加初始化器makes it compile on Clang

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30172483

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档