Просто
template <typename ...A>
struct CastAll{
template <typename ...B>
void cast_all(void(*fun)(B...), A...as){
fun(dynamic_cast<B>(as)...);
}
};
должно работать, и это работает с моей копией GCC. Однако необходимо внести некоторые изменения в ваш пример кода: A
должен быть полиморфным (что, в свою очередь, сделает B
полиморфным), чтобы dynamic_cast
был возможен (я добавил виртуальный деструктор по умолчанию, как обычно в моем примере кода) ; и вы, вероятно, намеревались использовать CastAll
как:
CastAll<A*, A*> cast;
cast.cast_all(foo, &a1, &a2);
То есть аргумент, который вы передаете cast_all
, является указателем на A
, который затем опускается до B
внутри тела. Кроме того, некоторые параметры шаблона выводятся 1 .
Это работает, потому что вы можете использовать несколько пакетов параметров (здесь A
и B
) в одном расширении пакета (здесь dynamic_cast
), при условии, что они имеют одинаковый размер; в противном случае, это тихая ошибка из-за SFINAE. От n3290, 14.5.3 / 5 шаблонов Variadic [temp.variadic]:
- [...] Шаблон расширения пакета должен называть один или несколько пакетов параметров
которые не расширяются вложенным пакетом расширения; такие пакеты параметров
называются нерасширенными пакетами параметров в шаблоне. Все
Пакеты параметров, расширенные расширением пакета, должны иметь одинаковые
количество аргументов указано. [...]
1 : Я не могу найти точную ссылку на то, разрешен ли здесь вычет или нет; GCC может даже вывести обе пачки, если я превращу CastAll
в полиморфный функтор. Я немного сомневаюсь, если это вообще обязательное поведение, но, по крайней мере, вы, похоже, знаете, как в любом случае указывать необусловленный аргумент.