C++ 如何对参数化模板函数进行类型推断

C++ 如何对参数化模板函数进行类型推断,c++,templates,template-argument-deduction,C++,Templates,Template Argument Deduction,您不能直接执行此操作,但可以将函数转换为函数对象: CallFuncs(1,2, Add, Mul); 或显式类型规范: CallFuncs(1., 2., Add{}, Mul{}); 如果T是void(例如,在std::plus{})中,plus::operator()推断参数和返回类型。典型的情况如下(稍作简化): template struct plus{ 模板 constexpr自动运算符()(Tp&t,Up&u)const{ 返回std::forward(t)+std::forw

您不能直接执行此操作,但可以将函数转换为函数对象:

CallFuncs(1,2, Add, Mul);
或显式类型规范:

CallFuncs(1., 2., Add{}, Mul{});
如果
T
void
(例如,在
std::plus{}
)中,
plus::operator()
推断参数和返回类型。典型的情况如下(稍作简化):

template struct plus{
模板
constexpr自动运算符()(Tp&t,Up&u)const{
返回std::forward(t)+std::forward(u);
}
};

如果可以将模板函数转换为函子类,则可以执行以下操作:

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);
    }
};
或者使用更相似的语法:

void FunctionInvokeTest() { CallFuncs(1, 2, Add{}, Mul{}); }
如果无法更改函数,则将其包装在lambda中可能会有所帮助:

constexpr Add add{};
constexpr Mul mul{};

void FunctionInvokeTest() { CallFuncs(1, 2, add, mul); }

将函数参数移动到模板中的解决方法

void FunctionInvokeTest() { CallFuncs(1, 2,
                                      [](auto lhs, auto rhs) { Add(lhs, rhs); },
                                      [](auto lhs, auto rhs) { Mul(lhs, rhs); }); }
模板
使用BinaryOp=void(F,F);//功能类型
//fns现在是一组函数对象,而不是类型
模板
void CallFuncs(fa,fb){
(fns(a,b),…);
};
void FunctionInvokeTest(){
//这些函数现在作为模板参数与所需的数值类型一起传递
CallFuncs(1,2);
}

不过请注意,由于整数参数W,这将使用
int
而不是
double
。。很酷,谢谢你!我花了5个小时搜索和阅读书籍,尝试不同的编码方式,在10分钟内从你那里得到了答案。@AlanBirtles我认为这很好。当我们调用std::max(…)时,我们仍然需要将数字指定为1.0而不是1。@WL_Law,我在使用此技术的标准库中添加了一个示例。
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); }
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); 
}