[英]How can I do the type deduction on parameterized template function
#include <iostream>
template <typename... Ts> void Print(Ts... args) {
(std::cout << ... << args) << std::endl;
}
template <typename T> void Add(T a, T b) { Print(a + b); }
template <typename T> void Sub(T a, T b) { Print(a - b); }
template <typename T> void Mul(T a, T b) { Print(a * b); }
template <typename F, typename... Fns> void CallFuncs(F a, F b, Fns... fns) {
(fns(a, b), ...);
};
void FunctionInvokeTest() { CallFuncs(1, 2, Add<int>, Mul<int>); }
int main() {
FunctionInvokeTest();
return 0;
}
我想將模板函數作為參數傳遞,如上所示。 該代碼有效。 但是,我必須將<int>
放在諸如Add<int>
類的函數之后。
如果這是不可扣除的上下文,那么還有另一種方法可以讓我這樣寫,其中Add
和Mul
仍然是模板函數嗎?
CallFuncs(1,2, Add, Mul);
你不能直接做,但是你可以把函數變成函數對象:
struct Add {
template<typename T>
void operator()(T a, T b) {
Print(a + b); }
};
struct Mul {
template<typename T>
void operator()(T a, T b) {
Print(a * b); }
};
template<typename F, typename... Fns>
void CallFuncs(F a, F b, Fns... fns) {
(fns(a, b), ...);
};
void FunctionInvokeTest() {
CallFuncs(1, 2, Add{}, Mul{});
}
T
將從a
和b
的類型推導出來。 在這個例子中,它將是int
。 要獲得double
,您需要double
參數:
CallFuncs(1., 2., Add{}, Mul{});
或顯式類型規范:
CallFuncs<double>(1, 2, Add{}, Mul{});
這與標准庫(C++14 起)中的“菱形”函子非常相似。 例如,std::plus
聲明是
template<class T = void>
struct plus;
如果T
為void
(例如,在std::plus<>{}
), plus::operator()
推導出參數和返回類型。 典型的實現看起來像這樣(有一些小的簡化):
template<> struct plus<void> {
template<typename Tp, typename Up>
constexpr auto operator()(Tp&& t, Up&& u) const {
return std::forward<Tp>(t) + std::forward<Up>(u);
}
};
如果您可以將模板函數轉換為函子類,您可以這樣做:
struct Add {
template <typename T>
void operator ()(T a, T b) const { Print(a + b); }
};
struct Sub
{
template <typename T> void operator() (T a, T b) const { Print(a - b); }
};
struct Mul
{
template <typename T> void operator() (T a, T b) const { Print(a * b); }
};
然后你可以做
void FunctionInvokeTest() { CallFuncs(1, 2, Add{}, Mul{}); }
或者有更多類似的語法:
constexpr Add add{};
constexpr Mul mul{};
void FunctionInvokeTest() { CallFuncs(1, 2, add, mul); }
如果您無法更改您的函數,將它們包裝在 lambda 中可能會有所幫助:
void FunctionInvokeTest() { CallFuncs(1, 2,
[](auto lhs, auto rhs) { Add(lhs, rhs); },
[](auto lhs, auto rhs) { Mul(lhs, rhs); }); }
通過將函數參數移動到模板中的解決方法
template <typename F>
using BinaryOp = void(F, F); // function type
// fns is now a pack of function objects instead of types
template <typename F, BinaryOp<F>... fns>
void CallFuncs(F a, F b) {
(fns(a, b), ...);
};
void FunctionInvokeTest() {
// the functions are now passed as template arguments alongside the desired numeric type
CallFuncs<float, Add, Mul>(1, 2);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.