在模板函数中推导模板函数(使用C ++概念)

Dongzin Choi

该代码导致错误error: no matching function to call to 'put'

#include <concepts>
#include <type_traits>  // for is_invocable_r_v
#include <iostream>

template <typename T>
T add(T a, T b)
{
    return a + b;
}

template <typename T, typename F>
    requires std::is_invocable_r_v<T, F, T, T>
void put(T& r, T a, T b, F f)
{
    r = f(a, b);
}

int main()
{
    int x;
    put(x, 1, 2, add);
    std::cout << "x = " << x << '\n';
}

这似乎是因为概念虽然可以约束模板参数,但无助于推导模板参数。

我可以put使用函数指针定义而不是引入参数F但是,它将排除更通用的函数对象,例如(捕获)用于的lambda f

template <typename T>
void put(T& r, T a, T b, T (f)(T, T))
{
    r = f(a, b);
}

当然,我可以更具体一些,put(x, 1, 2, add<int>)它将适用于这个简单的示例。但是,在更一般的情况下(例如编写库),我希望编译器为我做这件事,并add从外部上下文中确定适当的实例

是否可以让编译器知道F某种函数类型并使其推断呢?

不可预知的公主

额外的重载使编译器得以解决,add并且您仍然支持函数对象。

template <typename T>
T add(T a, T b)
{
    return a + b;
}

template <typename T, typename F>
    requires std::is_invocable_r_v<T, F, T, T>
void put(T& r, T a, T b, F f)
{
    r = f(a, b);
}


template <typename T>
void put(T& r, T a, T b, T(f)(T,T))
{
    r = f(a, b);
}

auto template_lambda_add = []<class T>(T a, T b) -> T { return a + b; };

int main()
{
    int x;
    put(x, 1, 2, add);
    std::cout << "x = " << x << '\n';
    put(x, 1, 2, std::plus<void>{});
    std::cout << "x = " << x << '\n';
    put(x, 1, 2, [](auto a, auto b){return a+b;});
    std::cout << "x = " << x << '\n';
    put(x, 1, 2, template_lambda_add);
    std::cout << "x = " << x << '\n';
}

编辑:

还支持模板lambda。香港专业教育学院增加了一个例子来演示。

作为补充说明,模板lambda的语法如下

auto lambda_add = []<class T>(T a, T b) -> T { return a + b; };

类似于以下内容的是模板变量声明。即用于创建lambda(而不是受试的lambda)的模板。

template <class T>
auto lambda_add = [](T a, T b) -> T { return a + b; };

edit2:更多的东西

我还可以使模板化的函数对象起作用吗?

是的 多数民众赞成std::plus<void>在基本上是什么

您必须通过模板操作符,而不是结构。例如

struct Add {
template <class T>
T operator()(T a, T b) { return a + b; } 
};

关于超载为何template <typename T> void put(T& r, T a, T b, T(f)(T,T)) { r = f(a, b); },起作用

基本上,编译器已经知道T前三个参数是什么,因此它可以使用它来找出如何实例化add为了更明确地说明我们想T从前三个参数而不是函数ptr参数推导出来的事实,我们可以std::type_identity像这样使用

template <typename T>
void put(T& r, T a, T b, std::type_identity_t<T(T,T)> f)
{
    r = f(a, b);
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

函数返回模板实体的概念

来自分类Dev

C ++概念和`std :: is_same`的模板参数推导问题

来自分类Dev

C ++中虚拟函数的概念

来自分类Dev

C ++概念:如何使用“概念”检查模板化结构的属性?

来自分类Dev

需要约束模板成员函数的概念定义

来自分类Dev

C递归函数调用概念

来自分类Dev

SFINAE内部概念模板参数

来自分类Dev

C ++模板函数类型推导

来自分类Dev

C ++模板函数类型推导

来自分类Dev

C ++中的“ Nil”的概念

来自分类Dev

C ++ 20中的概念

来自分类Dev

C ++中的重载概念

来自分类Dev

实现与C ++ 20概念配对的概念

来自分类Dev

在概念中将模板模板参数与CRTP一起使用

来自分类Dev

概念可以与模板模板参数一起使用吗?

来自分类Dev

真正基本的javascript函数概念

来自分类Dev

如何使用C ++ 20概念检查模板本身中的一些约束

来自分类Dev

使用概念或SFINAE检查类是否具有带有std :: array参数的模板化成员函数

来自分类Dev

授权中的角色概念

来自分类Dev

了解Java中的概念

来自分类Dev

OpenCV中的转换概念

来自分类Dev

JavaScript对象中的“ this”概念

来自分类Dev

PostgreSQL中的链表概念

来自分类Dev

了解Java中的概念

来自分类Dev

日食中的Aspectj概念

来自分类Dev

JavaScript对象中的“ this”概念

来自分类Dev

C程序概念

来自分类Dev

数组上的C概念

来自分类Dev

CLion对C ++概念的支持