Jen*_*nsB 6 c++ templates function enable-if
我正在尝试创建一个函数模板,它将函数模板作为模板参数,然后在使用传入的普通函数参数调用时返回该函数的结果。它将像这样使用:
auto fooPtr = func<std::make_unique, Foo>(...);
Run Code Online (Sandbox Code Playgroud)
该函数的要点是即使在让另一个函数执行实例的构造时也允许模板类型推导。我已经在代码中的很多地方手动执行此操作,如下所示:
auto fooPtr = std::make_unique<decltype(Foo{...})>(...);
Run Code Online (Sandbox Code Playgroud)
我从我发布的问题的答案中得到了辅助函数的想法。他建议为特定类型制作一个函数,但我想要一个可用于任何类型的函数。
到目前为止,这是我想到的:
template
<auto F, template<typename U> class T, typename... Args>
std::result_of_t<decltype(F)>
func(Args&&... args, std::enable_if_t<std::is_invocable_v<decltype(F), Args...>>* = nullptr)
{
return F<decltype(T{std::forward<Args>(args)...})>(std::forward<Args>(args)...);
}
Run Code Online (Sandbox Code Playgroud)
但我无法让它发挥作用。
我走在正确的轨道上吗?我想做的事情可能吗?
不幸的是,除非显式指定模板参数,否则无法将模板化函数作为模板参数传递,例如:
template<auto T>
auto func(auto&&... args) {
return T(std::forward<decltype(args)>(args)...);
}
struct Foo { Foo(int i) {} };
int main() {
auto unique_foo = func<std::make_unique<Foo, int>>(1);
}
Run Code Online (Sandbox Code Playgroud)
但是,您可以毫无问题地传递模板化函数对象,因此以下内容可以工作:
template<class T>
struct unique {
auto operator()(auto&&... args) {
return std::make_unique<T>(std::forward<decltype(args)>(args)...);
}
};
template<class T>
struct shared {
auto operator()(auto&&... args) {
return std::make_shared<T>(std::forward<decltype(args)>(args)...);
}
};
template<template<class> class F, class T, class... Args>
requires std::is_invocable_v<F<T>, Args...>
auto func(Args&&... args) {
return F<T>{}(std::forward<Args>(args)...);
}
struct Foo { Foo(int i) {} };
int main(){
auto foo_unique = func<unique, Foo>(1);
auto foo_shared = func<shared, Foo>(2);
}
Run Code Online (Sandbox Code Playgroud)
如果您还需要通过传递给的参数来推断类的模板参数(如链接的示例中所示),您可以添加处理模板化类型的std::make_unique
重载:func
template<template<class...> class T, class... Args>
using deduced_type = decltype(T{std::declval<Args>()...});
template<template<class> class F, template<class...> class T, class... Args>
requires std::is_invocable_v<F<deduced_type<T,Args...>>, Args...>
auto func(Args&&... args) {
return F<deduced_type<T, Args...>>{}(std::forward<Args>(args)...);
}
Run Code Online (Sandbox Code Playgroud)
T
它根据传入的参数将模板参数推导为您的类型。
template<class A, class B>
struct Foo { Foo(A,B) {} };
struct Bar { Bar(int i) {} };
int main(){
// automatically deduces the types for A, B in Foo based on arguments
auto foo_unique = func<unique, Foo>(1, 2);
// the normal overload of func handles non-templated classes:
auto bar_unique = func<unique, Bar>(1);
}
Run Code Online (Sandbox Code Playgroud)