Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.14.142.115] |
|
Сообщ.
#1
,
|
|
|
Собственно код (максимально упрощен, компилю в режиме C++17):
template<int param> struct a { template<int aa> static int constexpr AA = aa; }; template<int param> struct b { static int constexpr BB1 = a<3>::AA<2>; static int constexpr BB2 = a<param>::AA<2>; }; Не понимаю, почему BB1 компилится, а BB2 дает ошибку: a.cpp:12:47: error: expected primary-expression before ‘;’ token 12 | static int constexpr BB2 = a<param>::AA<2>; | ^ |
Сообщ.
#2
,
|
|
|
Даже я слегка подвис. Нечасто встречающаяся ситуация.
Дело в том, что внутри b<> имя a<param> является зависимым, поэтому что такое a<param>::AA, компилятору неведомо вплоть до точки инстанцирования. Только там, подставив конкретное param, он будет способен разобраться, что a<param>::AA – это тоже шаблон, а значит <2> является его инстацированием с аргументом 2. Однако ещё на первой фазе, при компиляции шаблона b<>, что значительно раньше его инстанцирования, он должен знать о том, что такое a<param>::AA. Т.к. у него нет никакой информации на этот счёт, он вынужден предположить, что это просто некое поле, и <2> является применением к нему арифметических операций < и >. Да, оно грамматически некорректно, однако по правилам Стандарта он не чекает корректность грамматики до момента инстанцирования, тем не менее неверный вывод о сути a<param>::AA он уже сделал, и в точке инстанцирования b<>::BB2 ты видишь последствия этого. Замечу, что c b<>::BB1 такой оказии не происходит, т.к. аргументы для a<> и a<>::AA<> указаны явно и не являются зависимыми от param, так что он способен — и должен — правильно определить грамматический смысл a<3>::AA<2> ещё на первой фазе. Исправить сие несложно, нужно лишь сообщить ему о сути a<>::AA ещё на первой фазе: static int constexpr BB2 = a<param>::template AA<2>; |
Сообщ.
#3
,
|
|
|
Цитата Qraizer @ Вот спасибо, добрый человек. У меня в исходнике a::AA - структура и компилятор требовал typename при объявлении типа BB2. И я в принципе понял, что ему нужен typename и в инициализаторе тоже, но вот как я его туда ни пытался всунуть - компилиться оно не хотело. Исправить сие несложно, |