2016-07-15 2 views
6

В следующем коде используется член перечисления m в качестве постоянного выражения, то есть в качестве параметра шаблона. Код компилируется под gcc, но не под clang (live demo). Кланг говорит: «ошибка: аргумент шаблона непигового типа не является постоянным выражением».Использование перечисления в качестве постоянного выражения. Какой компилятор прав?

Проблема может быть решена путем замены строки // 1 на A<tst<p>::m> a. Поэтому мой вопрос заключается не в том, как исправить эту проблему, но какой компилятор прав.

template<size_t n> struct A{}; 

template<size_t n> 
struct tst 
{ enum : size_t { m= n % 15 }; 

    template<size_t p> 
    void 
    call(tst<p> const &t2) { 
     A<t2.m> a; // 1 
    } 
}; 
+0

[Настоящие ссылки говорят] (http://en.cppreference.com/w/cpp/language/enum) «Когда перечисление с незащищенным доступом является членом класса, его счетчики могут быть доступны с помощью операторов доступа к членам класса' .' и '->' ". Тем не менее, он ничего не говорит о постоянстве выражений. –

+1

@JoachimPileborg Стандарт '§ 7.2.2' действительно говорит' Идентификаторы в списке нумераторов объявляются как константы и могут появляться там, где требуются константы. ' – lcs

ответ

3

В соответствии со стандартом, Кланг вправе отклонить код.

t2.m - выражение доступа к члену класса. [Expr.ref]/1 говорит:

[...] The postfix expression before the dot or arrow is evaluated; the result of that evaluation, together with the id-expression, determines the result of the entire postfix expression.

Там также примечание:

If the class member access expression is evaluated, the subexpression evaluation happens even if the result is unnecessary to determine the value of the entire postfix expression, for example if the id-expression denotes a static member.

Итак, Подвыражение t2 оценивается. [Expr.const] /2.9 говорит, что выражение e не может быть основной константным выражением, если оценка его результатов при оценке

an id-expression that refers to a variable or data member of reference type unless the reference has a preceding initialization and either

  • it is initialized with a constant expression or
  • its lifetime began within the evaluation of e ;

t2 ссылается на переменную ссылочного типа, которая не удовлетворяет пули, так t2.m не является постоянным выражением, поскольку оно не является основным постоянным выражением.


Все цитаты из N4594, текущий опубликованный рабочий проект. Текст немного изменился с C++ 11, но смысл в этом случае тот же.

+0

Thx. Кто-нибудь подал сообщение об ошибке для gcc? –

+0

@ClaasBontus У меня нет. Поиск в базе данных ошибок будет в порядке, но пока я не нашел времени для этого. – bogdan

+0

Возможно [Ошибка 39970] (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=39970). –

Смежные вопросы