C++类型擦除泛型函子对象



我有一堆实现通用调用运算符的类:

template<typename T = char>
struct match {
template<initer_of_type<T> IterT>
constexpr auto operator()(IterT iter) const -> std::optional<decltype(iter)> {
// ... function body
}
// ... some members
}
// ... more similar structs

在类模板中,其中运算符本身也是一个模板
注意:我在这里使用了一个概念,该概念用于接受任何返回特定值类型的输入迭代器:

template<typename IterT, typename T>
concept initer_of_type =
std::input_iterator<IterT>
&& std::is_same_v<typename IterT::value_type, T>;

这样,我就可以在任何可迭代的T容器上使用该算法。。。

我希望能够保存这些对象的数组,所有这些对象都具有相同的模板参数T,但可能是不同的类。我似乎既不能使用纯继承也不能使用类型擦除(至少在我看来是这样(,因为函数是一个模板。有什么好方法可以做到这一点吗?还是我在寻找错误的解决方案?

@chris评论很棒,如果我的理解是正确的,基本上它在IterT上添加了一层额外的抽象,从而使匹配函数能够被擦除(然后存储在某个容器中(

正如你所说:

我希望能够保存这些对象的数组,所有这些对象都具有相同的模板参数T,但可能是不同的类。

所以我们似乎必须添加一个新的抽象层来处理这个约束,chris的观点是从IterT开始。我想提供一个从ThreadExecutor中窃取的新视角。

一般来说,几乎所有的ThreadExecutor都有这样的接口:

std::future<R> execute(Func&& f, Args&&... args);

就像您的情况一样,args和return类型都是模板参数,ThreadExecutor还需要将这些用户传递任务存储在容器中。基本上,ThreadExecutor通过将用户传递任务包装在packaged_task中以擦除arg类型,然后将packaged_task包装在函数包装器或其他东西中以擦除返回类型来处理此问题。

这是一个非常天真的代码片段,直接使用了值捕获等,但我认为它可以表达基本思想。

struct Container{
template<typename IterT>
void add(match<IterT> func, IterT iter){
store_.push_back(std::function([=](){
std::packaged_task([=](){
return func(iter);
})();
}));
}
std::vector<std::function<void()>> store_;
};

最新更新