根据条件从另一个元组中创建一个引用元组

问题描述 投票:0回答:1

我有一个模板化结构

ContainerInner
,它有一个元组,其中包含来自其可变参数模板的类型向量,以及一个结构
Container
,其中包含在其模板中指定的
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;

    // It also crashes with std::tuple<Args&...> return type
    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
方法,以便它返回一个元组,其中包含对
ContainerInner
中包含指定类型的所有
m_containers
的引用,这是由静态
contains
方法处理的条件。我想我可以使用这样的概念:

template<typename InnerCnt, typename T>
concept ContainedType = 
    requires(T a, InnerCnt b) {
       b.contains<T>();
    };

递归迭代可变参数模板并使用

std::tuple_cat
构建最终数组,但不知道如何做到这一点。我该如何解决这个问题?

编辑。我解决了它,但可能不是以最佳方式。我在元组上添加了

Query
包装器并重载了
operator+
并用它来展开:

    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_));
}


// Inside Container
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;
}

它似乎有效,但我不确定编译器对此的优化效果如何,它实际上可能在运行时展开期间创建临时查询

c++ templates metaprogramming variadic-templates
1个回答
0
投票

来自

getTuples()
的问题:

  • 它是模板,但不使用其参数。可以删除。
  • std::make_tuple
    是为了推导它的参数,你直接想要
    std::tuple
    :
auto getTuples()
{
    auto tpl = std::tuple<Args&...>(std::get<Args>(m_containers)...);
    return tpl;
}

演示

© www.soinside.com 2019 - 2024. All rights reserved.