可变参数模板.一些问题

Variadic templates. Some issues

本文关键字:问题 变参 参数      更新时间:2023-10-16
template <class... T_values>
class Thing {
public:
  void something(T_values... values) {
    tuple_ = std::tuple<T_values...>(values...);
  }
  void do_something_with_values() {
     call_yadda_with_tuple(tuple_,
      std::index_sequence_for<T_value...>())
  }
  void yadda(T... values);
private:
  //The helper method.
  template<std::size_t... Is>
  void call_yadda_with_tuple(const std::tuple<T_values...>& tuple,
    std::index_sequence<Is...>) {
    yadda(std::get<Is>(tuple)...);
  }
  std::tuple<T_values...> tuple_;
};

以上源代码来自: https://www.murrayc.com/permalink/2015/12/05/modern-c-variadic-template-parameters-and-tuples/

我想问一些问题:

  1. 什么回std::index_sequence_for<T_value...>())
  2. 为什么在yadda(std::get<Is>(tuple)...);Is而不是Is...?因此,Is是什么意思? Is...在未包装(扩展)类型包装,但什么是Is
  3. 特别是,std::get适合(1)-(8)(http://en.cppreference.com/w/cpp/utility/tuple/get)
  4. 为什么call_yadda_with_tuplestd::index_sequence<Is...>.毕竟,这个论点是无名的,所以它是无用的。我想它与演绎类型有关,但我看不出它有什么帮助?

什么返回标准::index_sequence_for())?

假设T_value...是 T、T、T(即 3 种类型...

std::index_sequence<0, 1, 2>

为什么在yadda(std::get(tuple)...)中;有Is而不是Is...?因此,这意味着什么?是。。。在未包装(扩展)类型包,但什么是。

Is表示解压缩时Is... Is 的当前值"。尾随...会导致解压缩在其中使用 Is 的表达式。

特别是,哪个标准::适合(1)-(8)(http://en.cppreference.com/w/cpp/utility/tuple/get)

在本例中,元组引用是一个const std::tuple<T_values...>&,因此它将是数字 3。

为什么call_yadda_with_tuple会得到std::index_sequence。毕竟,这个论点是无名的,所以它是无用的。我想它与演绎类型有关,但我看不出它有什么帮助?

它的存在只是为了让Is...存在,因此允许您在序列中的所有Is进行扩展。

编辑:

下面是一个带有注释的示例,希望能解释正在发生的事情

#include <utility>
#include <tuple>
#include <string>
#include <iostream>
// for any value I, write a comma and space to stdout
// (i.e. ignore the value I)
template<std::size_t I>
void emit_sep()
{
    std::cout << ", ";
}
// specialise for when I is zero... no comma in this case
template<>
void emit_sep<0>()
{
}
// emit and value at some position I. Use emit_sep<I> to determine whether
// to print a separator
template<std::size_t I, class T>
void emit(const T& t)
{
    emit_sep<I>();
    std::cout << t;
}
// given a tuple type and a sequence of integers (Is...) emit the value
// at each index position of the tuple. Take care to emit a separator only
// before each element after the first one
template<class Tuple, size_t...Is>
void impl_show_it(const Tuple& tup, std::index_sequence<Is...>)
{
    using expand = int[];
    std::cout << "here are the indexes in the index_sequence: ";
    // the following line will expand (in our example) to:
    // void(int[] { 0, 
    //      (emit<0>(0), 0),
    //      (emit<1>(1), 0),
    //      (emit<2>(2), 0),
    //      });
    // and the optimiser will remove the operations which have no observable
    // side-effects (namely, building an array of ints which is never used)
    // so the code emitted will be equivalent to:
    // emit<0>(0); emit<1>(1); emit<2>(2);
    //
    void(expand {
        0,
        (emit<Is>(Is), 0)...
    });
    std::cout << std::endl;
    std::cout << "here are the values in the tuple: ";
    void(expand {
        0,
        (emit<Is>(std::get<Is>(tup)), 0)...
    });
    std::cout << std::endl;
}
// for some tuple type, compute the size of the tuple, build an index sequence
// representing each INDEX in the tuple and then use that sequence to call
// impl_show_it in order to actually perform the write
template<class Tuple>
void show_it(const Tuple& tup)
{
    constexpr auto tuple_size = std::tuple_size<Tuple>::value;
    auto sequence = std::make_index_sequence<tuple_size>();
    impl_show_it(tup, sequence);
}
// make a tuple and then show it on stdout
int main()
{
    auto t = std::make_tuple(6, std::string("hello"), 5.5);
    show_it(t);
}

预期成果:

here are the indexes in the index_sequence: 0, 1, 2
here are the values in the tuple: 6, hello, 5.5