【问题标题】:How to create custom integer sequence in C++如何在 C++ 中创建自定义整数序列
【发布时间】:2016-12-09 13:12:38
【问题描述】:

我有这样的功能:

template <typename ... Types>
void foo(const Types & ... values)
{
    // expected that 'values' is sequence like
    // '1, customvalue1, 2, customvalue2, 3,...'
}

第二个功能:

template <typename ... Types>
void bar(const Types & ... values)
{
    // where 'values' are any variables
    // some magic here
    foo((int_seq<sizeof...(Types)>, values)...);
}

我想将任何变量序列传递给 bar,以便将该序列转换为 '1, value1, 2, value2, 3, value3' 之类的序列>。因此,每个值都遵循其基本序列中的编号。但是我不能创建这个'魔术代码'来在这两种状态之间转换编译阶段的序列。

【问题讨论】:

  • 我假设bar 应该调用foo?不递归调用自己?
  • 你看过关联数组吗?对于这种类型的数据结构,这似乎是一个问题
  • 是的,我错了,当然是 'foo',而不是 'bar'

标签: c++ templates c++11 variadic-templates variadic-functions


【解决方案1】:

这是一个 C++14 解决方案,但所有必要的库部分也可以用 C++11 编写。

#include <iostream>
#include <tuple>
#include <utility>

template <typename ... Types>
void foo(const Types & ... values)
{
    using swallow = bool[];
    (void)swallow{ (std::cout << values << std::endl,false)... };
}

template <std::size_t N, bool = (N%2==0)>
struct pick {
    template<typename... Types>
    static std::size_t get(const std::tuple<Types...>&) { return N/2; }
};

template <std::size_t N>
struct pick<N,false> {
    template<typename... Types>
    static auto get(const std::tuple<Types...>& t) { return std::get<N/2>(t); }
};

template <std::size_t... Indices, typename ... Types>
void bar2(const std::index_sequence<Indices...>, const Types & ... values)
{
    auto x = std::tie(values...);
    foo(pick<Indices>::get(x)...);
}

template <typename ... Types>
void bar(const Types & ... values)
{
    bar2(std::index_sequence_for<Types...,Types...>(), values...);
}

int main()
{
    bar( "Hallo", 42, 1.23 );
}

Live example

它目前是从零开始的,但是在正确的位置使用+1 可以轻松解决这个问题。此外,它会创建一个中间 std::tuple 并引用这些值,如果性能是一个问题,可能存在更好的选择,但由于您没有使用 std::forward,我认为您可能可以接受较小的性能影响。

【讨论】:

  • 我会发现制作一个 tuple-of-2-tuples,然后展平,这是我的默认方法。在 C++17 中,我可以使用 if constexprtupler、lambda 和 std::apply 进行内联调用,这真的很有趣。
【解决方案2】:

不是很优雅,但是使用元组,std::tie 等...

以下示例应适用于 C++11

--- 编辑---

修改和统一(C++11 没有 C++14 元素)我的第一个例子。

不需要std::index_sequence(可以用简单的struct indSeq代替)或std::make_index_sequence(可以使用sizeof...(I)逐步构建索引序列);不再需要qux()

#include <tuple>
#include <iostream>


void foo ()
 { }

template <typename T0, typename ... Types>
void foo (const T0 & v0, const Types & ... values)
 {
   std::cout << "-- " << v0 << std::endl;

   foo(values...);
 }


template <std::size_t ...>
struct indSeq
 { };

template <std::size_t ... Is, typename ... Ts1>
void baz (std::size_t, const indSeq<Is...> &, const std::tuple<Ts1...> & t)
 { foo(std::get<Is>(t)...); }

template <std::size_t ... Is, typename ... Ts1, typename T0, typename ... Ts2>
void baz (std::size_t n, const indSeq<Is...> &, const std::tuple<Ts1...> & t,
          const T0 & v0, const Ts2 & ... vs)
 { baz(n+1U, indSeq<Is..., sizeof...(Is), sizeof...(Is)+1U>(),
       std::tuple_cat(t, std::tie(n), std::tie(v0)), vs...); }

template <typename ... Types>
void bar (const Types & ... values)
 { baz (1U, indSeq<>(), std::tuple<>(), values...); }

int main()
 {
   bar(11, 22L, "33", 44.44);
   return 0;
 }

ps:对不起,我的英语不好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-02
    • 1970-01-01
    • 2018-01-29
    • 1970-01-01
    • 2016-03-11
    • 2011-11-18
    • 2011-06-20
    • 1970-01-01
    相关资源
    最近更新 更多