c++ - 如何延迟初始化unique_ptrs的模板元组?

标签 c++ templates asynchronous c++14

我需要编写一个基于异步回调创建数据快照的类。例如,如果我有一个整数流和一个双流,则必须将数据推送到队列中,并在它们两个都有值时对数据进行处理。我的课看起来像这样的atm:

template<typename... Types>
class Dataholder{
private:
 std::deque<std::tuple<std::unique_ptr<Types>...>> data_frame_deque_;
public:
  template <class T>
  void push(T data); //find the next tuple that doesn't yet have value for type T and add it, or create new tuple
  void run_if_frame_ready(std::function<void (std::tuple<std::unique_ptr<Types>...>)&> fun); //run function fun, that accepts a tuple as defined in data_frame_queue_;
}
用法示例应如下所示:
Dataholder<int, double> holder;
void myProcessingFunction(std::tuple<int,double>& data)
{
 //do stuff
}
int main(void)
{
  holder.push(42);
  holder.push(3.14);
  holder.run_if_frame_ready(myProcessingFunction);
}
Dataholder::push()函数检查队列中的每个元组,是否存在框架,如果存在,则是否初始化相应的值。如果不是,则对其进行初始化,如果是,则将其移至下一个数据帧/创建一个新的空帧并将数据放在此处。Dataholder::run_if_frame_ready()函数检查队列中的第一帧是否已完全初始化。如果是,它将弹出并传递给给定的函数。
我的问题是,如何使用C++模板正确初始化所有成员?如何实现推送功能?我知道我可以使用std::is_same之类的东西进行检查,但是我不太了解如何进行检查。目前,如果所有类型都只使用一次是可以的,但是是否可以用相同类型的多个条目来实现?例如。那么对于像push(T data, int index)这样使用类的情况,则push函数可以是Dataholder<int, int>

最佳答案

做这么简单的事情给我带来了巨大的困难,我感到非常惊讶。在这个实现中,您有一个双端队列(deque),最终效率与手工操作一样高效,即,您不会在队列中循环寻找空条目。

template<typename>
void get();  // for ADL

template<typename... Types>
class Dataholder{
    using Deques = std::tuple<std::deque<std::unique_ptr<Types>>...>;

    Deques deq;

    template<typename F, size_t... Is>
    void run(F&& f, std::index_sequence<Is...>)
    {
        std::forward<F>(f)(*(get<Is>(deq).front())...);
    }

    template<size_t... Is>
    bool empty(std::index_sequence<Is...>) const
    {
        // mock fold expression
        bool e = false;
        char unused[] = {(e |= get<Is>(deq).empty())...};
        (void)unused;
        return e;
    }

    template<size_t... Is>
    void pop(std::index_sequence<Is...>)
    {
        char unused[] = {(get<Is>(deq).pop_front(), 0)...};
        (void)unused;
    }

public:
    // push by index
    template<size_t I, typename T>
    void push(T&& data)
    {
        using Tuple = std::tuple<Types...>;
        using type = std::tuple_element_t<I, Tuple>;
        get<I>(deq).emplace_back(new type(std::forward<T>(data)));
    }

    // push by type
    template<typename T>
    void push(T&& data)
    {
        using type = std::deque<std::unique_ptr<std::remove_reference_t<T>>>;
        get<type>(deq).emplace_back(new auto(std::forward<T>(data)));
    }

    bool empty()
    {
        return empty(std::index_sequence_for<Types...>{});
    }

    void pop()
    {
        pop(std::index_sequence_for<Types...>{});
    }

    // you don't want std::function for this
    template<typename F>
    void run_if_frame_ready(F&& f)
    {
        if(empty())
            return;
        run(std::forward<F>(f), std::index_sequence_for<Types...>{});
    }
};
并运行为
void f(int i, double d)
{
    std::cout << i << ' ' << d;
}

int main()
{
    Dataholder<int, double> holder;
    holder.push(42);
    holder.run_if_frame_ready(f);  // does nothing
    holder.push(3.14);
    holder.run_if_frame_ready(f);
}

关于c++ - 如何延迟初始化unique_ptrs的模板元组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64046258/

相关文章:

在异步调用返回之前发送的 HTTP 响应

Javascript/jQuery - 是否可以封装并返回异步执行函数的结果?

c++ - 如何将函数应用于可变参数列表并将它们分类为元组

c++ - 将枚举转换为成员变量 [问题] C++

c++ - 模板和信息丢失

c++ - RapidXML,读取和保存值

c# - 我如何知道最后一个 OutputDataReceived 何时到达?

c++ - 为什么在 C++ 中将类分解为多个源文件?

c++ - 在 C++ 中使用数组或 std::vectors,性能差距是什么?

c++ - 使用 libstdc++ 在字符串、u16string 和 u32string 之间转换