Рассмотрим код ниже:
template<char>
struct S { };
template<int N>
constexpr auto f(const char (&ref) [N]) {
return S<ref[0]>{};
}
int main() {
constexpr auto v = f("foo");
(void)v;
}
Он не компилируется, поскольку ref[0]
не является постоянным выражением.
В любом случае, приведенный ниже код компилируется нормально:
template<int N>
constexpr auto f(const char (&ref) [N]) {
return ref[0];
}
int main() {
constexpr auto v = f("foo");
(void)v;
}
Должны ли они оба компилироваться или не делать этого по более или менее одной и той же причине?
Из [expr.const] мы получаем следующее:
Условное выражение
e
является основным константным выражением, если только оценкаe
[...] не оценила бы одно из следующих выражений:
[...]
- id- выражение, которое относится к переменной или члену данных ссылочного типа, если только ссылка не имеет предшествующей инициализации и либо
- она инициализируется константным выражением, либо
- ее время жизни началось в пределах оценкиe
;
В любом случае, в этом случае он инициализируется постоянным выражением и время жизни такое же, как у e
, поэтому правило не применяется.
Что не так в моих рассуждениях?
В качестве побочного вопроса я бы спросил, можно ли использовать такой массив или его часть в качестве аргумента шаблона.
S<ref[0]>
не может быть создан во время выполнения. - person kennytm   schedule 17.10.2016constexpr auto v = f("foo");
. - person skypjack   schedule 17.10.2016char a[10]; randomize(a); f(a)
. - person kennytm   schedule 17.10.2016