This code works fine in Clang 3.5:
#include <iostream>
#include <string>
void callFuncs() {}
template<typename Func, typename ...Funcs>
void callFuncs(const Func &func, const Funcs &...funcs)
{
func();
callFuncs(funcs...);
}
template<typename ...Types>
void callPrintFuncs()
{
callFuncs(([] { std::cout << Types() << std::endl; })...);
}
int main()
{
callPrintFuncs<int, float, double, std::string>();
}
However, in GCC 4.9, I get the following error instead:
test.cpp: In lambda function:
test.cpp:16:54: error: parameter packs not expanded with '...':
callFuncs(([] { std::cout << Types() << std::endl; })...);
^
test.cpp:16:54: note: 'Types'
test.cpp: In function 'void callPrintFuncs()':
test.cpp:16:58: error: expansion pattern '<lambda>' contains no argument packs
callFuncs(([] { std::cout << Types() << std::endl; })...);
So, which compiler has a bug, Clang or GCC? The Clang behavior makes the most sense to me at least.
gcc is broken here. There are rules against unexpanded parameter packs in the standard, but the above parameter pack is expanded.
It is expanded after the end of innermost statement it is in, but the standard does not require that the parameter packs be expanded by the end of every statement.
The fact that gcc got it wrong is sort of understandable; naively, you'd think that a parameter pack can only be within one statement, and the failure to expand at the end of the statement is fatal. But lambdas let you nest statements within statements.
A general workaround can be to pass in one lambda and pass in a "tag" type to it.
template<class T>struct tag_t{using type=T;};
template<class Tag>using type_t=typename Tag::type;
template<typename Func, typename ...Ts>
void callOnEachOf(Func&&func, Ts&&...ts)
{
using discard=int[];
(void)discard{0,((void)(
func(std::forward<Ts>(ts))
),0)...};
}
template<typename ...Types>
void callPrintFuncs()
{
callOnEachOf(
[](auto tag){
using Type=type_t<decltype(tag)>;
std::cout << Type() << std::endl;
},
tag_t<Types>...
);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With