enable_if模板参数为lambda(具有特定签名) [英] enable_if template param is lambda (with particular signature)
问题描述
我有这样的东西:
template<typename T>
class Image {
Image(int w, int h, T defaultVal){
for(int i=0; i<h; i++)
for(int j=0; j<w; j++)
pixel(j, i) = defaultVal;
}
template<typename F>
Image(int w, int h, F initializer){
for(int i=0; i<h; i++)
for(int j=0; j<w; j++)
pixel(j, i) = initializer(j, i);
}
// ...
};
我的意图是能够像这样实例化Image
:
My intention is to be able to instantiate an Image
like this:
Image<int> img0(w, h, 0); // image of zeroes
Image<int> imgF(w, h, [](int j, int i){ // checkerboard image
return (j/10+i/10) % 2;
});
但是,第二个构造函数签名当然会与第一个构造函数签名冲突.为了解决此冲突,我想限制第二个构造函数的可能模板实例化.
But of course the second constructor signature will conflict with the first constructor signature. To resolve this conflict I want to restrict the second constructor's possible template instantiations.
我不想使其变得过于复杂.你能帮助我吗?我的尝试:
I don't want to make it too complicated. Can you help me? My attempt:
template<typename F, typename = std::enable_if_t< // what now? how to check that F is callable (and if simple to check, with appropriate signature)
推荐答案
您正在寻找 std::is_invocable
:
You're looking for std::is_invocable
:
template<typename F, typename = std::enable_if_t<
std::is_invocable<F&, int, int>>
F&
,因为您将其作为左值调用,然后,它只是参数类型的列表.
F&
because you're invoking it as an lvalue, and then after that it's just a list of types of parameters.
以上要求使用C ++ 17.它可以在C ++ 14上实现,但是在您的情况下,我们也可以采用更简单的方法,然后执行以下操作:
The above requires C++17. It is implementable on C++14, but in your case we can also take a much simpler approach and just do:
template <typename F, typename = decltype(std::declval<F&>()(1, 1))>
F&
的原因与上述相同,因此表达式的其余部分更加熟悉.由于我们使用int
进行调用,因此我们不在乎INVOKE
允许的其他操作(例如,指向成员的指针).
F&
for the same reason as above, and the rest of the expression is more familiar. Since we're calling with int
s we don't care about the other things that INVOKE
allows for (e.g. pointers to members).
这篇关于enable_if模板参数为lambda(具有特定签名)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!