我正在尝试编写一个函数,该函数通过使用自由格式谓词测试对象序列来构造位掩码:
template<typename... Args, bool(*TestingFunc)(Object, Args...)>
inline uint32_t getMask(const std::vector<Object>& objects, Args... args)
{
uint32_t mask = 0;
for(size_t i = 0; i < objects.size(); i++)
if(TestingFunc(objects[i], args...))
mask |= 1 << i;
return mask;
}
但是,上面的代码不起作用:gcc / clang在每次调用函数时报告no matching function for call to
(clang的note: candidate template ignored: invalid explicitly-specified argument for template parameter 'Args'
,gcc的note: template argument deduction/substitution failed:
;调用为{{ 1}},谓词为getMask<int, pred1>(objects, 10)
,请参见下面的信息。
有一些定义明确的谓词,它们接受不同数量的特定于bool pred1(Object, int)
调用的附加参数。每个谓词都是一个简单的函数。理想情况下,应该编写getMask()
函数,以便我可以这样调用它:
getMask()
这是我程序中的一个热点;性能至关重要。 /* bool predicate1(Object, size_t, size_t, int, int); */
mask = getMask<predicate1>(objects, a.height(), b.width(), 10, 15);
/* ... */
/* bool predicate2(Object, int, int); */
mask = getMask<predicate2>(objects, x, y);
和谓词用内联标记。该代码必须用C ++ 11(不是C ++ 14或更高版本)编写。
那么,getMask()
应该如何写?
答案 0 :(得分:0)
我建议您遵循标准库,仅按值传递可调用的模板化类型。如果不是函数指针,它将被内联。
template<class... Args, class F>
inline uint32_t getMask(F f, const std::vector<Object>& objects, Args... args)
{
uint32_t mask = 0;
for(size_t i = 0; i < objects.size(); i++)
if(f(objects[i], args...))
mask |= 1 << i;
return mask;
}
如果有ctce,有一种非常简单的方法可以将函数指针转换为无状态可调用对象:
使用std::integral_constant<decltype(p), p>
。在C ++ 17中,也许有一个助手。
template <auto f>
using to_type = std::integral_constant<decltype(f), f>;
getMask(to_type<checkit>(), somedata, arg0, arg1, arg2);
getMask([](auto... x){ return checkit(x...); }, somedata, arg0, arg1, arg2);
答案 1 :(得分:-1)
在c ++ 17中,您可以编写
template<auto TestingFunc, typename... Args>
inline uint32_t getMask(const std::vector<Object>& objects, Args... args)
{
uint32_t mask = 0;
for(size_t i = 0; i < objects.size(); i++)
if(TestingFunc(objects[i], args...))
mask |= 1 << i;
return mask;
}
在C ++ 11中,您还需要执行更多操作:
首先,我们不能使用模板函数,因为它需要部分重载。因此,只需采用具有静态功能的结构:
struct Object
{
Object( int _val ):val{_val}{}
int val;
};
template <class F, F f> struct caller;
template <class Obj, class... Args, bool (* TestingFunc)(Obj, Args...)>
struct caller<bool (*)(Obj, Args...), TestingFunc>
{
static uint32_t Do( std::vector<Object>& objects, Args... args)
{
uint32_t mask = 0;
for(size_t i = 0; i < objects.size(); i++)
if(TestingFunc(objects[i], args...))
mask |= 1 << i;
return mask;
}
};
bool checkit( const Object& o, int i )
{
return o.val==i;
}
int main()
{
std::vector<Object> objects;
objects.emplace_back(1);
objects.emplace_back(2);
objects.emplace_back(3);
// The ugly thing before c++17 is, that you have to specify the
// function type itself as a template parameter. As said: C++17
// has offered exactly the feature of auto here in template parameter lists
// to allow deduction of type from parameter.
std::cout << caller<decltype(&checkit), checkit>::Do(objects,3) << std::endl;
}
但是我认为,耗时的事情根本不是使用函数指针。在您手动修改很多东西之前,先进行测量,测量,测量!