【问题标题】:Constructing templated tuple types构造模板元组类型
【发布时间】:2019-08-09 15:42:05
【问题描述】:

我正在尝试编写这样的函数

template<
        bool b, RT = std::conditional_t<b,
               std::tuple<int, int, int, int>,
               std::tuple<int, int, int, int, double, double, double, double>
        >
RT function()
{
    int i1, i2, i3, i4;

    if constexpr(b)
    {
        double i5, i6, i7, i8;
        return { i1, i2, i3, i4, i5, i6, i7, i8 };
    }
    else
    {
        return { i1, i2, i3, i4 };
    }
}

有没有办法为元组创建一个模板化的typedef,以便我可以简化上面的函数

template<typename T, int N>
using tuple_t = std::tuple<T, T, ... N1 times>

template<typename T1, int N1, typename T2, int N2>
using tuple_t = std::tuple<T1, T1, ... N1 times, T2, T2, ... N2 times>

【问题讨论】:

  • 为什么不干脆做using some_name = std::tuple&lt;int, int, int, int&gt;; using another_name = std::tuple&lt;int, int, int, int, double, double, double, double&gt;;之类的事情?
  • @NathanOliver 这只是一个代表性的例子。我有 T1T2N1N2 等不同组合的用例。

标签: c++ templates tuples variadic-templates template-meta-programming


【解决方案1】:

您可以使用返回类型推导并将聚合初始化替换为对make_tuple的调用:

template<bool b>
auto function()
{
    int i1, i2, i3, i4;

    if constexpr(b)
    {
        double i5, i6, i7, i8;
        return std::make_tuple(i1, i2, i3, i4, i5, i6, i7, i8);
    }
    else
    {
        return std::make_tuple(i1, i2, i3, i4);
    }
}

如果您仍然需要返回类型,您可以简单地创建一个 trait:

template <bool b>
using return_t = decltype(function<b>());

【讨论】:

  • 这是一个非常好的和简单的解决方案。谢谢!
【解决方案2】:

来不及玩了?

回答您的一般性问题

有没有办法为元组创建一个模板化的 typedef 以便我可以简化上面的函数

template<typename T, int N>
using tuple_t = std::tuple<T, T, ... N1 times>

template<typename T1, int N1, typename T2, int N2>
using tuple_t = std::tuple<T1, T1, ... N1 times, T2, T2, ... N2 times>

我提出以下完整且可编译的 C++14 示例

#include <tuple>
#include <utility>

template <typename T, std::size_t>
using get_type = T;

template <typename T, std::size_t ... Is>
constexpr std::tuple<get_type<T, Is>...>
   get_tuple_t (std::index_sequence<Is...>);

template <typename T, std::size_t N>
using tuple_t_1 = decltype(get_tuple_t<T>(std::make_index_sequence<N>{}));

template <typename T1, std::size_t N1, typename T2, std::size_t N2>
using tuple_t_2 = decltype(std::tuple_cat(
      std::declval<tuple_t_1<T1, N1>>(),
      std::declval<tuple_t_1<T2, N2>>()));

int main ()
 {
   using t1a = tuple_t_1<int, 4u>;
   using t1b = std::tuple<int, int, int, int>;
   using t2a = tuple_t_2<int, 4u, double, 4u>;
   using t2b = std::tuple<int, int, int, int, double, double, double, double>;

   static_assert( std::is_same<t1a, t1b>::value, "!" );
   static_assert( std::is_same<t2a, t2b>::value, "!" );
 }

【讨论】:

  • 非常酷的解决方案,我不知道std::index_sequence
  • @Bilentor - 不幸的是,std::make_index_sequencestd::index_sequence 只能从 C++14 开始使用
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多