Я пишу шаблонный обработчик событий, который позволяет пользователю отправлять события (в виде структур) подключенным слушателям.
У меня есть функция-член "emit", которая будет создавать объект Event из предоставленных параметров шаблона variadic и пересылать событие.Однако я хотел бы предоставить специализированную функцию «emit», которая будет определять, является ли предоставленный аргумент заранее созданным объектом Event, и в этом случае я мог бы переслать событие, не делая лишней копии.
Мой начальныйпопытка ...
template <typename T_Event>
class EventHandler
{
public:
template <typename... T_Args>
void emit(T_Args&&... args)
{
printf("variadic\n");
deliver(T_Event {std::forward<T_Args>(args)...});
}
void emit(const T_Event& event)
{
printf("reference\n");
deliver(event);
}
...
};
Я использовал следующую логику, чтобы попробовать обе функции испускает, но оказывается, что VARIADIC шаблон функция всегда имеет приоритет над константной опорной функцией.
1009 *
После еще одного исследования мне удалось достичь своей цели, определив две версии функции шаблона variadic и используя enable_if для выполнения правильной.
template <typename... T_Args>
void emit(T_Args&&... args)
{
printf("variadic\n");
T_Event event {std::forward<T_Args>(args)...};
deliver(event);
}
template <typename... T_Args, typename = std::enable_if<std::is_same<const T_Event&, T_Args...>::value>>
void emit(T_Args&&... args)
{
printf("reference\n");
deliver(std::forward<T_Args>(args)...);
}
Это решение работало именно так, как мне нужно, когда я компилируюс GCC, но если я скомпилирую с CLANG, я получаю следующее сообщение об ошибке:
call to member function 'emit' is ambiguous
handler.emit(event);
candidate function [with T_Args = <EventB &>]
void emit(T_Args&&... args)
candidate function [with T_Args = <EventB &>, $1 =
std::__1::enable_if<false, void>]
void emit(T_Args&&... args)
Я предполагаю, что я близок к правильному решению, может кто-нибудь объяснить, что я делаю неправильно?