很抱歉在这里跳来跳去,但是我的google-foo对于模板函数(或函数模板?)及其在函数模板(或模板函数?)中的重载不屑一顾。
我试图用另一个可能占用lambda的功能模板重载一个功能模板,但我不知道为什么未选择它
这是我的确切情况
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)”分配给“ 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);});
答案 0 :(得分:0)
根据CPP标准草案中的[expr.prim.lambda]/2,
lambda表达式是prvalue,其结果对象称为闭包对象。
因此,当您将lambda作为参数传递时,它将被视为prvalue,并且选择的重载是这样的:
template< typename buffer_t, typename value_t >
void fill(buffer_t buffer, const value_t value)
但是编译失败,因为在实例化功能模板时将lamdba分配给了float
。
答案 1 :(得分:0)
据我所知,这是不可能的。
感谢Igor-Tandetnik指出没有函数模板专门化之类的东西;只有函数重载。
因此,当涉及到它时,我试图用另一个带有相同数量参数的函数模板来使一个函数模板重载。这是模板+超载分辨率进入扣除/分辨率的百慕大三角形的地方。 https://en.cppreference.com/w/cpp/language/function_template#Function_template_overloading。最终可能会获得成功,但是向其他人提供如何到达那里的地图也很困难,并且代码的可读性和可维护性很重要。
区分这两种实现的最佳方法是SFINAE和一些额外的类型特征,但是C ++ 11没有提供用于标识lambda的任何类型特征,这让我自己定义了一个特征类。 P.W指出lambda的类型是一个闭包对象。这使得定义类型特征类来识别lambda(甚至是任意参数的函子)变得非常困难。
我尝试过,但是失败了。如果这对其他人有用,我将分享我的尝试。也许其他人可以找到解决方案:
// 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 似乎可以满足我的要求...
// 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 {};