意外的非常量std :: initializer_list

时间:2013-04-15 19:27:18

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

我正在玩索引技巧,看​​看我可以去哪里,并遇到一个奇怪的错误......首先,简单的不那么老的指数:

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

那么,有人可以向我解释在上面的代码中对于编译器究竟有什么不够的常量吗?

编辑:该问题的后续行动

1 个答案:

答案 0 :(得分:1)

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

具体做法是:  它的返回类型及其参数的类型(如果有的话)是文字的 类型(见x2.2)。具体而言,字面类型包括bool, int或double;  它的身体是形式的复合陈述 {return expr; } 其中expr是这样的,如果任意常量表达式 适当的类型将替换expr中的参数 结果表达式是一个常量表达式,如定义的那样 x2的介绍段落。表达式expr称为a 潜在的持续表达。