enable_if模板param是lambda(具有特定签名)

时间:2018-06-14 13:49:58

标签: c++ templates lambda c++14 enable-if

我有这样的话:

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

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;
});

但是第二个构造函数签名当然会与第一个构造函数签名冲突。要解决此冲突,我想限制第二个构造函数的可能模板实例化。

我不想让它变得太复杂。你能帮助我吗?我的尝试:

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)

1 个答案:

答案 0 :(得分:4)

您正在寻找std::is_invocable

template<typename F, typename = std::enable_if_t<
    std::is_invocable<F&, int, int>>

F&因为你将它作为左值调用,然后它就是一个参数类型列表。

以上需要C ++ 17。它可以在C ++ 14上实现,但在你的情况下我们也可以采用一种更简单的方法来做:

template <typename F, typename = decltype(std::declval<F&>()(1, 1))>

F&出于与上述相同的原因,表达式的其余部分更为熟悉。由于我们使用int进行调用,因此我们不关心INVOKE允许的其他内容(例如指向成员的指针)。