3

我正在编写一个数值模拟程序。我的一个函数需要回调。该函数作为模板函数实现,回调作为模板类实现,因此可以内联对回调的调用。

现在,我的函数变得越来越复杂,我想以一种定义明确、可自动检查的方式声明回调的签名。所以我查看了 C++ Concepts TS。

这就是问题所在。我想定义一个仿函数的概念std::array,例如

struct sum {
    template <class Float, size_t N>
    Float operator()(std::array<Float, N> const& arr) {
       // return the sum of arr...
    }
};
struct avg {
    template <class Float, size_t N>
    Float operator()(std::array<Float, N> const& arr) {
        // return the average of arr...
    }
};

注意:这是一个简化的示例。更改函子的签名(例如,更改std::array为一对迭代器)并非不可能,但不是首选。

怎么写一个概念来表示sumavg上面的通用接口?

首先我试过:

template <class F, class Float, size_t N>
concept bool ArrayProcessor = requires (F func, std::array<Float, N> arr) {
    func(arr);
};

但这会导致(在我看来)一个丑陋的代码;在使用回调的模板函数的定义中,其声明如下所示:

template <ArrayProcessor<double, 1> CB, ...>
void simulate(CB const& callback, ...) {
    ...
}

<double, 1>部件是编译通过所需的虚拟部件。这种解决方案很难接受,因为模板参数callback.operator()可能会在内部发生变化simulate;可以将不同类型和大小的std::arrays 传递给它。

其次我试过:

template <class F>
concept bool ArrayProcessor = requires (F func, auto arr) {
    func(arr);
};

此代码格式错误,因为在 requires-expression 中使用 constrained-type-specifier 格式错误(参考:https ://groups.google.com/a/isocpp.org/forum/m/#!topic/concepts /_gHn0wJJNGA)。顺便说一句,gcc 6.1.0 会产生一个内部编译错误。

所以,问题是:如何为以模板类作为参数的仿函数定义一个概念(最好没有变通方法)?

通过我的搜索,我得到的印象是 C++ 概念可能不是为这样的用途而设计的。也非常感谢对 C++ 概念的替代方案的建议。

(可能与使用 Concepts Lite 为具有成员函数模板的类型指定概念有关,但我不知道它是否重复)

4

0 回答 0