7

Я немного искал трюк с индексами, чтобы увидеть, с чем я могу пойти, и наткнулся на странную ошибку ... Во-первых, простые не-старые индексы:Неожиданный непостоянный std :: 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]; 
    } 
}; 

Итак, я попытался создать функцию, которая возвращает копию array после добавления 1 к каждому из своих членов:

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 

Итак, может кто-нибудь объяснить мне, что именно не является достаточно постоянным для компилятора в приведенном выше коде?

EDIT: прослеживаний для этого вопроса

+2

Истеризатор A *, равный или равный *, не является выражением и может, как таковое никогда не быть постоянным выражением, является тем, что, по моему мнению, является проблемой здесь. – Xeo

+0

Фактически, Clang 3.2 отклоняет даже инициализацию 'a' –

+0

@AndyProwl Я знаю, Clang не поддерживает N3471, вот почему :) – Morwenn

ответ

0

От: человек сам http://www.stroustrup.com/sac10-constexpr.pdf

В частности: его возвращаемый тип, и типы его параметры (если есть), являются буквами типов (см. x2.2). Для конкретности литеральные типы включают bool, int или double; его тело является составной формулой формы {return expr; } где expr таково, что если произвольные постоянные выражения заменяют соответствующие типы в выражениях expr, то полученное выражение является константным выражением, как определено в вводном параграфе x2. Выражение expr называется потенциальным постоянным выражением .