[英]Variadic template with function, inputs and outputs types
I'm trying to understand how to create and call variadic templates with function, inpus args and output args types.我试图了解如何使用 function、inpus args 和 output args 类型创建和调用可变参数模板。 I wrote this toy example:
我写了这个玩具示例:
#include <tuple>
template<typename Func, typename... Inputs, typename... Outputs>
std::tuple<double, Outputs...> foo(int init, Func&& func, Inputs&&... args) {
return std::forward<Func>(func)(init, std::forward<Inputs>(args)...);
};
int main () {
int init = 6;
double mult = 2.3;
std::tuple<double, double> bar = foo(
init,
[](int init_, double mult_) {
double res = init_ * mult_;
return std::make_tuple(res, 4.1);
},
mult
);
int out = std::get<0>(bar);
return out;
}
However, it doesn't compile.但是,它不会编译。 How should I modify it to get 13 as result?
我应该如何修改它以获得13作为结果?
I get this error message:我收到此错误消息:
<source>: In function 'int main()':
<source>:11:41: error: conversion from 'tuple<double>' to non-scalar type 'tuple<double, double>' requested
11 | std::tuple<double, double> bar = foo(
| ~~~^
12 | init,
| ~~~~~
13 | [](int init_, double mult_) {
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
14 | double res = init_ * mult_;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~
15 | return std::make_tuple(res, 4.1);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
16 | },
| ~~
17 | mult
| ~~~~
18 | );
| ~
<source>: In instantiation of 'std::tuple<double, Outputs ...> foo(int, Func&&, Inputs&& ...) [with Func = main()::<lambda(int, double)>; Inputs = {double&}; Outputs = {}]':
<source>:18:5: required from here
<source>:5:72: error: could not convert 'main()::<lambda(int, double)>(init, std::forward<double&>((* & args#0)))' from 'tuple<double, double>' to 'tuple<double>'
5 | return std::forward<Func>(func)(init, std::forward<Inputs>(args)...);
| ^
| |
| tuple<double, double>
You can write this template function as:您可以将此模板 function 编写为:
template<typename Func, typename... Inputs>
auto foo(int init, Func&& func, Inputs&&... args) {
return std::forward<Func>(func)(init, std::forward<Inputs>(args)...);
}
The problem with the original version is with typename... Outputs
, they cannot be deduced.原始版本的问题在于
typename... Outputs
,它们无法推断。 You would need to specify them explicitly - but this is impossible because there are two variadic packs in that template - so it is impossible to say where Inputs... ends and where Outputs starts.您需要明确指定它们 - 但这是不可能的,因为该模板中有两个可变参数包 - 因此无法说出 Inputs... 的结束位置和 Outputs 的开始位置。
Alternatively - you can just specify one result typename - and specify that type:或者 - 您可以只指定一个结果类型名称 - 并指定该类型:
template<typename Output, typename Func, typename... Inputs>
Output foo(int init, Func&& func, Inputs&&... args) {
return std::forward<Func>(func)(init, std::forward<Inputs>(args)...);
}
and call:并致电:
std::tuple<double, double> bar = foo<std::tuple<double, double>>(
init,
[](int init_, double mult_) {
double res = init_ * mult_;
return std::make_tuple(res, 4.1);
},
mult
);
Or move the function template into class template as static function:或者将 function 模板作为 static ZC1C425268E68385D1AB5074FCC17 移动到 class 模板中
template<typename ...Output>
struct Foo
{
template <typename Func, typename... Inputs>
static std::tuple<Output...> foo(int init, Func&& func, Inputs&&... args) {
return std::forward<Func>(func)(init, std::forward<Inputs>(args)...);
}
};
and call:并致电:
auto bar = Foo<double, double>::foo(
init,
[](int init_, double mult_) {
double res = init_ * mult_;
return std::make_tuple(res, 4.1);
},
mult
);
The body of foo
isn't available to deduce Outputs...
, so they are deduced as empty. foo
的主体不可用于推断Outputs...
,因此它们被推断为空。
To enforce that it returns a std::tuple
where the first element is double
, you can write a trait.要强制它返回第一个元素为
double
的std::tuple
,您可以编写一个特征。
template <typename>
struct is_tuple_of_double : std::false_type {};
template <typename... Others>
struct is_tuple_of_double<std::tuple<double, Others...>> : std::true_type {};
template <typename T>
constexpr bool is_tuple_of_double_v = is_tuple_of_double<T>::value;
template<typename Func, typename... Inputs>
auto foo(int init, Func&& func, Inputs&&... args) {
static_assert(is_tuple_of_double_v<decltype(std::forward<Func>(func)(init, std::forward<Inputs>(args)...)>);
return std::forward<Func>(func)(init, std::forward<Inputs>(args)...);
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.