【问题标题】:Unexpected non-constant std::initializer_list意外的非常量 std::initializer_list
【发布时间】:2013-04-08 01:04:04
【问题描述】:

我正在玩弄索引技巧,看​​看我可以去哪里,遇到了一个奇怪的错误......首先,简单的不太旧的索引:

template<std::size_t...>
struct indices {};

template<std::size_t N, std::size_t... Indices>
struct make_indices:
    make_indices<N-1, N-1, Indices...>
{};

template<std::size_t... Indices>
struct make_indices<0, Indices...>:
    indices<Indices...>
{};

我创建了一个从std::initializer_list 派生的编译时数组类,并使其可索引(假设您的编译器支持N3471。无论如何它将在下一个标准中出现)。这里是:

template<typename T>
struct array:
    public std::initializer_list<T>
{
    constexpr array(std::initializer_list<T> values):
        std::initializer_list<T>(values)
    {}

    constexpr auto operator[](std::size_t n)
        -> T
    {
        return this->begin()[n];
    }
};

所以,我尝试创建一个函数,在向其每个成员添加 1 后返回 array 的副本:

template<typename T, std::size_t... I>
auto constexpr add_one(const array<T>& a, indices<I...>)
    -> const array<T>
{
    return { (a[I]+1)... };
}

要完成代码,这是我的主要内容:

int main()
{
    constexpr array<int> a = { 1, 2, 3 };
    constexpr auto b = add_one(a, make_indices<a.size()>());

    return 0;
}

我不认为代码会编译,但我对错误消息感到非常惊讶(这里是ideone 代码):

In function 'int main()':
error: 'const smath::array<int>{std::initializer_list<int>{((const int*)(& const int [3]{2, 3, 4})), 3u}}' is not a constant expression

那么,有人可以向我解释一下上面代码中的编译器究竟是什么不够恒定吗?

编辑:对该问题的跟进

【问题讨论】:

  • A brace-or-equal 初始化器不是表达式,因此永远不会是常量表达式,这就是我认为的问题所在。
  • 其实Clang 3.2甚至拒绝a的初始化
  • @Morwenn:这里,{ (a[I]+1)... } 不是一个表达式。它是一种用于初始化的语言结构,但它本身并不是一个表达式(尽管初始化列表的各个元素是)。由于它不是表达式,所以它不能是 constant 表达式。这就是我认为 Xeo 的意思。
  • 正如@Andy 所说。真的,如果你想要一个编译时数组,只需将std::array 与扩充一起使用,它可以通过聚合初始化来初始化。
  • @Morwenn 啊,现在我明白了......很脏,我喜欢它:D 但还有另一个问题:initializer_list 本身不是文字类型(不一定是,即 AFAIK 没有保证)。 constexpr 对象必须是文字类型 [dcl.constexpr]/9 并且您的 array 不是文字类型,因为它继承了非文字类型。您也可以尝试定义一个constexpr std::initializer_list&lt;int&gt; mylist; - 由于同样的原因而失败。还禁止constexpr ctors 具有非文字类型的参数 [dcl.constexpr]/4。

标签: c++ c++11 variadic-templates compile-time initializer-list


【解决方案1】:

来自:男人本人 http://www.stroustrup.com/sac10-constexpr.pdf

具体来说: 它的返回类型和它的参数类型(如果有的话)是文字 类型(见 x2.2)。具体而言,文字类型包括 bool、 整数或双精度; 它的主体是形式的复合语句 {返回表达式; } 其中 expr 是这样的,如果任意常量表达式 适当的类型被替换为 expr 中的参数,然后 结果表达式是一个常量表达式,定义在 x2 的介绍性段落。表达式 expr 称为 潜在的常量表达式。

【讨论】:

    猜你喜欢
    • 2013-12-20
    • 1970-01-01
    • 1970-01-01
    • 2013-08-12
    • 2017-11-27
    • 2020-06-11
    • 2023-03-30
    • 2012-04-15
    • 1970-01-01
    相关资源
    最近更新 更多