Я пытаюсь реализовать настраиваемый обратный вызов во время компиляции для поведения вызовов синхронизации / асинхронности.
Вот первый подход к этому:
//emit type's
enum EEmitType
{
SYNC,
ASYNC,
};
//general
template<EEmitType et, typename... Args>
class callback_impl;
//implementation
template<EEmitType et, typename R, typename... Args>
class callback_impl<et, R(Args...)>
{ /*todo*/ };
//................................................................
//convert enum value to type or SFINAE
template <EEmitType et>
using callback_emit_type = std::integral_constant<EEmitType, et>;
//(for default SYNC)
template <typename T>
struct is_emit_type : std::false_type {};
//(for any other implementation)
template <EEmitType et>
struct is_emit_type<callback_emit_type<et>> : std::true_type {};
//................................................................
//metafunction
template <typename T>
using is_emit_type_t = typename is_emit_type<T>::type;
//................................................................
//for decl. like: callback<void()>
template <typename _unused, typename... Args>
struct construct_callback_impl
{
//alias on implementation
using type = callback_impl<SYNC, Args...>;
};
//for decl. like: callback<callback_emit_type<ASYNC>, void()>
template <typename EEmitType, typename... Args>
struct construct_callback_impl<typename
std::enable_if<is_emit_type_t<EEmitType>::value>::type, EEmitType, Args...>
{
//alias on implementation
using type = callback_impl<EEmitType::value, Args...>;
};
//................................................................
//user alias
template <typename... Args>
using callback = typename construct_callback_impl<Args...>::type;
Теперь ИСПОЛЬЗУЯ:
callback<int(int)> ff_s; //<-- uses undefined class 'callback_impl<SYNC>'
callback<callback_emit_type<ASYNC>, int(int)> ff_a; //<--OK
Конечно, потому что первые аргументы съедают, и для компиляции успеха это должно быть записано как:
callback<int(int), int(int)> ff_s
Но, конечно, это не неприемлемо.
Хорошо, тогда я пытаюсь извлечь EEmitType из Args ...
//for decl. like: callback<void()>
template <typename... Args>
struct construct_callback_impl
{
//alias on implementation
using type = int; //temporary stub
};
//for decl. like: callback<callback_emit_type<ASYNC>, void()>
template <typename... Args>
struct construct_callback_impl<typename std::enable_if<is_emit_type_t< typename std::tuple_element_t<0, std::tuple<Args...> >::type >::value>::type, Args...>
{
//alias on implementation
using type = int; //temporary stub
};
НО теперь я получаю:
error C2338: tuple index out of bounds
note: see reference to class template instantiation 'std::tuple_element<0,std::tuple<>>' being compiled