是否可以以這種方式使用可變函數/模板?

我想知道,如果給定以下約束條件,是否可以使用可變函數/模板將可變數量的參數(其本身是函數的返回值)傳遞到可變函數中。

Constraints:

  1. 沒有STL/Boost/其他庫。
  2. No loops/recursion.
  3. 與C++17或更早版本兼容(除C++17外無其他內容)。

Brief example:

using fn = F(...);
fn* func = (fn*) addr;
value = (*func)(pop_t(outputstack,o_stackidx,o_stacksize)...);
push_t(outputstack,o_stackidx,o_stacksize, value);

fn*是一個函數指針(從函數的已知user-defined內存地址轉換而來),它接受數量可變的pop_t參數(從堆棧中彈出的值),這些值(outputstack,o_stackidx,o_stacksize是靜態的,本身不需要是可變的。本質上,我想知道是否有可能讓pop_t函數重復一個可變的次數a.)根據fn能夠接受的參數的適當數量,或者B.)使用指定重復次數的user-defined整數。

例如,假設用戶要輸入sin或atan2函數,這兩個函數分別采用不同數量的參數sin(x)和atan(y,x)。對于這兩個各自的函數,函數調用表達式如下所示:

sin -> (*func)(pop_t(outputstack,o_stackidx,o_stacksize)); 

atan2 -> (*func)(pop_t(outputstack,o_stackidx,o_stacksize),pop_t(outputstack,o_stackidx,o_stacksize)); 

具有N個參數的函數通過調用pop_tN次從堆棧中彈出N個值。

Reproducible example:

template<class U, class I>
U pop_t(U* stack, I &stackidx, I &stacksize) {
    if(stacksize>0) {
        stacksize--;
        stackidx = stackidx--;
        return stack[stackidx];
    }
    else {
        return stack[stackidx];
    }
}

int main() {
    float outputstack[2] = {3.141/2,1};
    o_stackidx = 2;
    o_stacksize = 2;
    long addr = (long)&atan2;
    using fn = F(...);
    fn* func = (fn*) addr;
    // Unknown variadic function pointer
    value = (*func)(pop_t(outputstack,o_stackidx,o_stacksize,nt)...);

    return 0;

}
? 最佳回答:

看來,您希望根據參數的數量多次重復語句,在這種情況下,您可以接受C++模板的幫助:

#include <cstddef>
#include <utility>

template <size_t N>
struct repeater {
    template <typename F, typename ...Args>
    static void do_work(F&& f, Args&&... args) {
        f(std::forward<Args>(args)...);
        repeater<N - 1>::do_work(f, args...);
    }
};

template <>
struct repeater<0> {
    template <typename F, typename ...Args>
    static void do_work(F&&, Args&&...) {}
};

template <size_t N, typename F, typename ...Args2>
void repeat_for_n(F&& to_rep, Args2&&... args) {
    repeater<N>::do_work(to_rep, args...);
}

template <typename T1, typename ...Args1, typename F, typename ...Args2>
void repeat_for_args(T1(Args1...), F&& to_rep, Args2&&... args) {
    repeat_for_n<sizeof...(Args1)>(to_rep, args...);
}

然后你可以這樣使用它:

repeat_for_args(some_function, [&]() {
    (*func)(pop_t(outputstack,o_stackidx,o_stacksize))
});

如果您想先自己試一試:

編輯1:要在模板的幫助下生成參數中具有N重復類型的函數指針類型,可以執行以下操作:

首先,您需要定義這個幫助器類:

#include <tuple>

template <typename, typename>
struct make_sig_from_tuple;

template <typename R, typename ...Args>
struct make_sig_from_tuple<R, std::tuple<Args...>> {
    using type = R(*)(Args...);
};

template <typename R, typename ...Args>
using make_sig_from_tuple_t = typename make_sig_from_tuple<R, Args...>::type;

然后我們可以這樣做,

template <typename T, size_t N>
struct generate_sig_impl {
    using type = decltype(std::tuple_cat(std::declval<std::tuple<T>&>(), std::declval<typename generate_sig_impl<T, N - 1>::type&>()));
};

template <typename T>
struct generate_sig_impl<T, 0> {
    using type = std::tuple<>;
};

template <typename R, typename T, size_t N>
struct generate_sig {
    using type = make_sig_from_tuple_t<R, typename generate_sig_impl<T, N>::type>;
};

template <typename R, typename T, size_t N>
using generate_sig_t = typename generate_sig<R, T, N>::type;

現在可以使用它來轉換僅具有N值的變量函數,而不必多次顯式聲明類型中的參數:

repeat_for_args(reinterpret_cast<generate_sig_t<float, float, 3>>(function_with_variadic_arguments), /* ... */);
// Equivalent to: repeat_for_args(reinterpret_cast<float(*)(float, float, float)>(function_with_variadic_arguments), /* ... */);

編輯2:由于注釋中的OP也希望顛倒參數的順序,因此可以使用以下方法:

template <typename Arg1, typename ...Args>
struct reverse_func_sig_impl {
    using type = decltype(std::tuple_cat(std::declval<typename reverse_func_sig_impl<Args...>::type&>(), std::declval<std::tuple<Arg1>&>()));
};

template <typename Arg1>
struct reverse_func_sig_impl<Arg1> {
    using type = std::tuple<Arg1>;
};

template <typename>
struct reverse_func_sig;

template <typename R, typename... Args>
struct reverse_func_sig<R(Args...)> {
    using type = make_sig_from_tuple_t<R, typename reverse_func_sig_impl<Args...>::type>;
};

template <typename FuncPtr>
using reverse_func_sig_t = typename reverse_func_sig<FuncPtr>::type;

然后像這樣使用它:

repeat_for_args(reinterpret_cast<generate_sig_t<int(float, int)>>(function_with_variadic_arguments), /* ... */);
// Equivalent to: repeat_for_args(reinterpret_cast<int(int, float)>(function_with_variadic_arguments), /* ... */);

Demo

主站蜘蛛池模板: 日本无卡码免费一区二区三区| 亚洲一区二区影院| 日本不卡一区二区视频a| 麻豆天美国产一区在线播放| 国产精品无码一区二区三区免费| 日韩精品无码久久一区二区三| 亚洲电影一区二区| 动漫精品第一区二区三区| 麻豆一区二区在我观看| 精品在线一区二区| 亚洲AV无码国产一区二区三区| 亚洲一区精品无码| 国产精品无码一区二区在线观一| 无码成人一区二区| 亚洲色婷婷一区二区三区| 爆乳熟妇一区二区三区| 怡红院一区二区在线观看| 久久久久人妻一区二区三区| 中文字幕一区二区三区四区| 日本一区二区三区精品中文字幕| 日本在线视频一区二区| 亚洲一区二区三区高清在线观看 | 大香伊人久久精品一区二区| 无码少妇一区二区三区| 日韩人妻无码一区二区三区久久| 久久久99精品一区二区| 日本精品一区二区三区在线观看| 一级毛片完整版免费播放一区| 动漫精品专区一区二区三区不卡 | 国产精品区AV一区二区| 亚洲日本一区二区三区在线不卡| 国产精品福利一区| 丰满岳乱妇一区二区三区| 波多野结衣高清一区二区三区 | 日韩亚洲AV无码一区二区不卡| 色婷婷一区二区三区四区成人网 | 99久久精品国产一区二区成人| 国产精品一区二区久久| 麻豆一区二区免费播放网站| 蜜桃AV抽搐高潮一区二区| 精品国产一区二区三区香蕉|