Take the following:
#include <utility>
#include <functional>
#include <iostream>
struct FooType
{
FooType(std::tuple<std::function<void()>, std::function<void()>> t)
{
std::get<0>(t)();
std::get<1>(t)();
}
};
int main()
{
FooType foo(
std::make_tuple(
[]() { std::cout << "a\n"; },
[]() { std::cout << "b\n"; }
)
);
}
It builds and runs fine with GCC 4.9 and higher, but with GCC 4.8 (which is my build system) the following compiler error results:
In file included from main.cpp:2:0:
/usr/include/c++/4.8/functional: In substitution of 'template<class _Res, class ... _ArgTypes> template<class _Functor> using _Invoke = decltype (std::__callable_functor(declval<_Functor&>())((declval<_ArgTypes>)()...)) [with _Functor = std::_Tuple_impl<1ul, main()::__lambda1>; _Res = void; _ArgTypes = {}]':
/usr/include/c++/4.8/functional:2257:9: required from 'constexpr std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(std::_Tuple_impl<_Idx, _UHead, _UTails ...>&&) [with _UHead = main()::__lambda0; _UTails = {main()::__lambda1}; long unsigned int _Idx = 0ul; _Head = std::function<void()>; _Tail = {std::function<void()>}]'
/usr/include/c++/4.8/tuple:556:60: required from 'constexpr std::tuple<_T1, _T2>::tuple(std::tuple<_U1, _U2>&&) [with _U1 = main()::__lambda0; _U2 = main()::__lambda1; <template-parameter-2-3> = void; _T1 = std::function<void()>; _T2 = std::function<void()>]'
main.cpp:21:5: required from here
/usr/include/c++/4.8/functional:2181:71: error: 'main()::__lambda1' is not an accessible base of 'std::_Tuple_impl<1ul, main()::__lambda1>'
using _Invoke = decltype(__callable_functor(std::declval<_Functor&>())
^
Presumably I've hit a "bug" in GCC 4.8's experimental C++11 implementation, but I can't find any discussion about it online. Is this issue familiar to anyone? Is there a cheap workaround?
Passing std::function
in tuples is core to the design I've just created — shame on me for building it in Coliru without switching to GCC 4.8 specifically until the end!
Creating a tuple with explicit template arguments works as a workaround:
#include <utility>
#include <functional>
#include <iostream>
struct FooType
{
FooType(std::tuple<std::function<void()>, std::function<void()>> t)
{
std::get<0>(t)();
std::get<1>(t)();
}
};
int main()
{
FooType foo(
std::make_tuple
<
std::function<void()>,
std::function<void()>
>(
[]() { std::cout << "a\n"; },
[]() { std::cout << "b\n"; }
)
);
}