使用接受 lambda 的模板函数重载 [英] Overload of template function with one that accepts lambdas

查看:57
本文介绍了使用接受 lambda 的模板函数重载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

很抱歉跳到这里,但我的 google-foo 不适合模板函数(或函数模板?)及其与函数模板(或模板函数?)的重载.

Apologies for jumping here, but my google-foo is not up to snuff for template functions (or function templates?) and their overloads with function templates (or template functions?).

我试图用另一个可以接受 lambda 的函数模板重载一个函数模板,但我不知道为什么它没有被选中

I'm trying to overload a function template with another function template that can take a lambda and I can't figure out why it's not selected

这是我的确切场景

template< typename buffer_t, typename value_t >
void fill(buffer_t buffer, const value_t value)
{
    std::fill(buffer.begin(), buffer.end(), value);
}

//partial specialization for buffers
template< typename sample_t, stride_t stride=1u >
void fill(Buffer<sample_t,stride> &buffer, const sample_t value)
{
    std::fill(buffer.begin(), buffer.end(), value);
}

//overload for filling a buffer with a callable
template< typename sample_t, stride_t stride=1u >
void fill(Buffer<sample_t,stride> buffer, const std::function<sample_t(size_t,size_t)> filler)
{
    const size_t N = buffer.samples();
    for(size_t i = 0; i < N; ++i) buffer[i] = filler(i, N);
}

这是我的错误

错误:从不兼容的类型 'const (lambda at )' 分配给 'float'注意:在函数模板特化 'Smule::Audio::fill, (lambda at )' 的实例化中要求fill(input, [](size_t i, size_t N){ return (float)std::sin(2.0 * M_PI * 4.0 * (double)i/(double)N); });

error: assigning to 'float' from incompatible type 'const (lambda at )' note: in instantiation of function template specialization 'Smule::Audio::fill, (lambda at )' requested here fill(input, [](size_t i, size_t N){ return (float)std::sin(2.0 * M_PI * 4.0 * (double)i / (double)N); });

推荐答案

据我所知,这是不可能的.

Best I can tell, it's impossible.

感谢 Igor-Tandetnik 指出没有函数模板特化这样的东西;只有函数重载.

Thanks to Igor-Tandetnik for pointing out that there's no such thing as a function template specialization; There's only function overloads.

因此,归根结底,我试图用另一个具有相同数量参数的函数模板来重载一个函数模板.这是模板 + 重载解析进入演绎/解析百慕大三角的地方.https://en.cppreference.com/w/cpp/language/function_template#函数_模板_重载.最终有可能通过,但向其他人提供您如何到达那里的地图也非常困难,代码可读性+可维护性很重要.

So when it comes down to it, I'm trying to overload a function template with another function template with the same number of arguments. This is where templates + overload resolution gets into the bermuda triangle of deduction/resolution. https://en.cppreference.com/w/cpp/language/function_template#Function_template_overloading. It's possible to get through eventually, but providing anybody else with a map of how you got there is also quite difficult, and code readability+maintainability matters.

区分这两种实现的最好方法是 SFINAE 和一些额外的类型特征,但是 C++11 没有提供任何类型特征来识别 lambda,这会让我自己定义一个特征类.P.W 指出 lambda 的类型是一个闭包对象.这使得定义类型特征类来识别 lambda(甚至任意参数的函子)非常具有挑战性.

The best way to differentiate these two implementations is SFINAE and some extra type traits, but C++11 doesn't provide any type traits for identifying lambdas, which would leave me to define a trait class myself. P.W pointed out that the type of a lambda is a closure object. This makes defining a type traits class to identify lambdas (or even functors of arbitrary arguments) quite challenging.

我尝试过,但失败了.如果它对其他人有用,我会分享我的尝试.也许其他人可以找到解决方案:

I tried, but failed. In case it's useful to anybody else I'll share what I tried. Maybe somebody else can get to a solution:

// Give myself a default-defined is_callable trait that is false_type
template< typename T, typename enable=void > struct is_callable: public std::false_type {};
//specializations for callable types:

// functors and lambdas
template< typename T, typename ...arg_t >
struct is_callable< decltype(T::operator(arg_t...)) >: public std::true_type {};

同样,这不起作用.这是一个编译错误,我还没有弄清楚是否可以使用参数引用运算符.以下重载do 似乎做我想做的...

Again, this didn't work. It's a compile error, and I haven't quite figured out if it's even possible to reference an operator with arguments. The following overloads do seem to do what I want...

// functions
template< typename T >
struct is_callable< T, typename std::enable_if< std::is_function<T>::value >::type >: public std::true_type {};

// std::function
template< typename ret_t, typename ...arg_t >
struct is_callable< std::function<ret_t(arg_t...)> >: public std::true_type {};

这篇关于使用接受 lambda 的模板函数重载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆