使用接受 lambda 的模板函数重载 [英] Overload of template function with one that accepts lambdas
问题描述
很抱歉跳到这里,但我的 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屋!