-namespace bits {
-
- // Compute the maximum size taken by any of the given types:
- template <class... T> struct max_size;
- template <>
- struct max_size<> : public std::integral_constant<std::size_t, 0> {};
- template <class T>
- struct max_size<T> : public std::integral_constant<std::size_t, sizeof(T)> {};
- template <class T, class... U>
- struct max_size<T, U...> : public std::integral_constant<std::size_t,
- (sizeof(T) > max_size<U...>::value) ? sizeof(T) : max_size<U...>::value
- > {};
-
- struct whatever {};
-
- // What we can store in a Task:
- typedef void* ptr_callback;
- struct funcptr_callback {
- // Placeholder for any function pointer:
- void(*callback)();
- void* data;
- };
- struct member_funcptr_callback {
- // Placeholder for any pointer to member function:
- void (whatever::* callback)();
- whatever* data;
- };
- constexpr std::size_t any_size = max_size<
- ptr_callback,
- funcptr_callback,
- member_funcptr_callback
- >::value;
- typedef std::array<char, any_size> any_callback;
-
- // Union of what we can store in a Task:
- union TaskErasure {
- ptr_callback ptr;
- funcptr_callback funcptr;
- member_funcptr_callback member_funcptr;
- any_callback any;
- };
-
- // Can we copy F in Task (or do we have to use the heap)?
- template<class F>
- constexpr bool isUsableDirectlyInTask()
- {
- // TODO, detect availability std::is_trivially_copyable / workaround
-#if 1
- // std::is_trivially_copyable is not available before GCC 5.
- return false;
-#else
- // The only types we can portably store directly in the Task are the
- // trivially copyable ones (we can memcpy) which are small enough to fit:
- return std::is_trivially_copyable<F>::value &&
- sizeof(F) <= sizeof(bits::any_callback);
-#endif
- }
-
-}
-