基于条件从元组生成引用元组的C++实现方案
C++模板容器筛选问题
问题背景
我定义了如下模板结构:
ContainerInner:内含存储可变模板类型vector的元组m_elements,提供contains静态方法判断是否包含指定类型,以及get方法获取对应vector的引用。Container:内含ContainerInner类型的元组m_containers,当前getTuples方法返回所有ContainerInner的引用元组。
template<typename... Args> struct ContainerInner { std::tuple<std::vector<Args>...> m_elements; template<typename T> static constexpr bool containsOne() { return (std::is_same_v<T, Args> || ...); } template<typename... T> static constexpr bool contains() { return (containsOne<T>() && ...); } template<typename T> std::vector<T> &get() { return std::get<std::vector<T>>(m_elements); } }; template<typename... T> struct ArgList { template<typename... TTS> using add = ArgList<T..., ContainerInner<TTS...>>; }; template<typename ListArgs> struct Container; template<typename... Args> struct Container<ArgList<Args...>> { std::tuple<Args...> m_containers; // 改成std::tuple<Args&...>返回类型也会崩溃 template<typename... T> inline auto getTuples() { auto tpl = std::make_tuple<Args&...>(std::get<Args>(m_containers)...); return tpl; } template<typename... T> ContainerInner<T...> &get() { return std::get<ContainerInner<T...>>(m_containers); } }; using MyArgList = ArgList<> ::add<char, int> ::add<char, float> ::add<char, int, float>; int main(int argc, char* args[]) { Container <MyArgList> cnt; auto arr = cnt.getTuples<float>(); std::get<ContainedType<char, int>>(arr).get<int>().push_back(3); std::cout << typeid(arr).name() << std::endl; std::cout << cnt.get<char, int>().get<int>().size() << std::endl; }
需求
修改getTuples方法,使其返回m_containers中所有包含指定类型的ContainerInner的引用元组,判断条件由contains静态方法处理。我尝试用如下concept实现:
template<typename InnerCnt, typename T> concept ContainedType = requires(T a, InnerCnt b) { b.contains<T>(); };
但找不到递归遍历可变模板并通过std::tuple_cat构建结果的方法,该如何解决?
已实现方案及疑问
我通过封装Query结构体(重载operator+)实现了功能,但不确定编译器优化效果,担心运行时会生成临时Query对象:
template<typename... Args> struct Query { std::tuple<Args...> m_tpl; template<typename... TT> constexpr inline auto operator+(const Query<TT...> &rhs_) { return Query<Args..., TT...>(std::tuple_cat(m_tpl, rhs_.m_tpl)); } template<typename... TT> constexpr inline auto &get() { return std::get<ContainerInner<TT...>&>(m_tpl); } }; template<typename LST, typename CONTAINER_INNER> constexpr inline auto getQueryElem(CONTAINER_INNER &t_) { return Query<>(); } template<typename LST, typename CONTAINER_INNER> requires Contained<CONTAINER_INNER, LST> constexpr inline auto getQueryElem(CONTAINER_INNER &t_) { return Query(std::tuple<CONTAINER_INNER&>(t_)); } // 放在Container内部的getTuples方法 template<typename... T> constexpr inline auto getTuples() { return (getQueryElem<Typelist<T...>>(std::get<Args>(m_containers)) + ...); } int main(int argc, char* args[]) { Container <MyArgList> cnt; auto arr = cnt.getTuples<int>(); std::cout << typeid(arr).name() << std::endl; cnt.get<char, int>().get<int>().push_back(5); arr.get<char, int>().get<int>().push_back(-99); std::cout << cnt.get<char, int>().get<int>() << std::endl; std::cout << arr.get<char, int>().get<int>() << std::endl; }
内容的提问来源于stack exchange,提问作者SavedowW
相关产品推荐
相关产品推荐

