Это работает не во всех функциональных случаях, но с указателями функций должно работать.
Если вы определяете пользовательский шаблон следующим образом
template <typename>
struct baz;
template <typename R, typename ... Args>
struct baz<R(*)(Args...)>
{ using retType = R; };
ваш пример станет
template <typename T, typename Func>
void Example(Func func)
{
static_assert(std::is_same<typename baz<Func>::retType,
std::unique_ptr<T>>::value, "!");
}
Ниже приводится полный пример компиляции
#include <type_traits>
#include <memory>
template <typename>
struct baz;
template <typename R, typename ... Args>
struct baz<R(*)(Args...)>
{ using retType = R; };
template <typename T, typename Func>
void Example(Func func)
{
static_assert(std::is_same<typename baz<Func>::retType,
std::unique_ptr<T>>::value, "!");
}
struct Foo
{
Foo (int i) : My_I{i}
{ }
Foo () : My_I{99}
{ }
~Foo() = default;
int My_I;
};
std::unique_ptr<Foo> bar0 ()
{ return std::make_unique<Foo>(11); }
std::unique_ptr<Foo> bar1 (int)
{ return std::make_unique<Foo>(11); }
std::unique_ptr<Foo> bar2 (int, long)
{ return std::make_unique<Foo>(11); }
int main ()
{
Example<Foo>(&bar0);
Example<Foo>(&bar1);
Example<Foo>(&bar2);
}
К сожалению, это решение работает только с указателями на функции, а не с (например) лямбда-функцией (если она не конвертируется в указатели на функции) или с классами с operator()
.
Если вы можете использовать C ++ 17 - и я полагаю, что это ваш случай, если вы используете std::invoke_result
- вы также можете использовать автоматические направляющие вычеты для std::function
.
Итак, в C ++ 17 вы можете забыть структуру baz
и просто написать
template <typename T, typename Func>
void Example(Func func)
{
static_assert(std::is_same<
typename decltype(std::function{func})::result_type,
std::unique_ptr<T>>::value, "!");
}
или, по вашему Register()
методу
template<typename My_Type, typename Func>
static bool Register(Func func)
{
static_assert(std::is_same<
typename decltype(std::function{func})::result_type,
std::unique_ptr<My_Type>>::value, "!");
bool isRegistered = false;
if (GetCreateFunctions().end() == GetCreateFunctions().find(typeid(My_Type)))
{
GetCreateFunctions()[typeid(My_Type)] = reinterpret_cast<void*>(func);
isRegistered = true;
}
return isRegistered;
}