我正在编写一个数值模拟程序。我的一个函数需要回调。该函数作为模板函数实现,回调作为模板类实现,因此可以内联对回调的调用。
现在,我的函数变得越来越复杂,我想以一种定义明确、可自动检查的方式声明回调的签名。所以我查看了 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
为一对迭代器)并非不可能,但不是首选。
怎么写一个概念来表示sum
和avg
上面的通用接口?
首先我试过:
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::array
s 传递给它。
其次我试过:
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 为具有成员函数模板的类型指定概念有关,但我不知道它是否重复)