代码之家  ›  专栏  ›  技术社区  ›  Museful

如果模板参数为lambda(具有特定签名),则启用

  •  2
  • Museful  · 技术社区  · 6 年前

    我有件事:

    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 回复  |  直到 6 年前
        1
  •  4
  •   Barry    6 年前

    你在找 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&P; 出于上述相同的原因,其余的表达方式更为熟悉。因为我们打电话来 int 我们不在乎其他事情 INVOKE 允许(例如指向成员的指针)。