[英]Variadic template with function, inputs and outputs types
我試圖了解如何使用 function、inpus args 和 output args 類型創建和調用可變參數模板。 我寫了這個玩具示例:
#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;
}
但是,它不會編譯。 我應該如何修改它以獲得13作為結果?
我收到此錯誤消息:
<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>
您可以將此模板 function 編寫為:
template<typename Func, typename... Inputs>
auto foo(int init, Func&& func, Inputs&&... args) {
return std::forward<Func>(func)(init, std::forward<Inputs>(args)...);
}
原始版本的問題在於typename... Outputs
,它們無法推斷。 您需要明確指定它們 - 但這是不可能的,因為該模板中有兩個可變參數包 - 因此無法說出 Inputs... 的結束位置和 Outputs 的開始位置。
或者 - 您可以只指定一個結果類型名稱 - 並指定該類型:
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)...);
}
並致電:
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
);
或者將 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)...);
}
};
並致電:
auto bar = Foo<double, double>::foo(
init,
[](int init_, double mult_) {
double res = init_ * mult_;
return std::make_tuple(res, 4.1);
},
mult
);
foo
的主體不可用於推斷Outputs...
,因此它們被推斷為空。
要強制它返回第一個元素為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.