簡體   English   中英

具有 function 的可變參數模板,輸入和輸出類型

[英]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... ,因此它們被推斷為空。

要強制它返回第一個元素為doublestd::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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM