Ответ 1
Конечно. Вам нужен контекст, который разрешает расширение пакета - простой - это скопированный список инициализаторов, который также имеет преимущество для оценки слева направо:
using expander = int[];
(void) expander { 0, ((void) As::id(), 0)... };
-
...
расширяет шаблон слева от него; в этом случае шаблон является выражением((void) As::id(), 0)
. -
,
в выражении - это оператор запятой, который оценивает первый операнд, отбрасывает результат, затем оценивает второй операнд и возвращает результат. -
As::id()
существуетAs::id()
для защиты от перегруженногоoperator,
и может быть опущен, если вы уверены, что ни один из вызововAs::id()
не вернет то, что перегружает оператор запятой. -
0
в правой части оператора запятой состоит в том, чтоexpander
является массивомint
s, поэтому все выражение (которое используется для инициализации элемента массива) должно оцениваться какint
. - Первый
0
гарантирует, что мы не пытаемся создать недопустимый массив 0-размера, еслиAs
- пустой пакет.
Демо.
В С++ 17 (если нам повезет), все тело C::id
можно заменить на двоичное выражение сложения: (A::id(), ... , (void) As::id());
Demo.