将数组与可变参数模板

时间:2015-12-07 22:03:00

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

我现在正在学习C ++ 11,C ++ 14和C ++ 1z中的模板和模板。我正在尝试编写一个带有内部类的可变参数类模板,它将int与每个模板参数相关联 - 并且有一个返回其数组表示的constexpr方法。

假设我确保模板不能接收两个与参数相同的类型。我在考虑这样做:

template <typename... Types>
struct MyVariadicTemplate {
    //we know that all types in Types... are different
    template <int... Values> 
    struct MyInnerTemplate {
        //I need to make sure that sizeof...(Values) == sizeof...(Types)
        constexpr std::array<int, sizeof...(Values)> to_array() {
            std::array<int, sizeof...(Values)> result = {Values...};
            return result;
            // this is only valid since C++14, as far as I know
        }
    };
};

此代码应该有效(如果不是,我很想知道原因)。现在,我想添加另一个内部模板:

template <typedef Type>
struct AnotherInnerTemplate {};

有一个public typedef,代表MyInnerTemplate,其中Type位于Types...,其他位置为零 - 此处我迷路了。我不知道该怎么办

我很感激任何关于如何做到这一点的暗示 - 如果我朝着错误的方向前进,我希望有人能给我一个如何做到这一点的暗示。

2 个答案:

答案 0 :(得分:1)

  template <int size, int... Values> struct AnotherImpl {
    using Type = typename AnotherImpl<size - 1, Values..., 0>::Type;
  };

  template <int... Values> struct AnotherImpl<0, Values...> {
    using Type = Inner<Values...>;
  };

  template <class T> struct Another {
    using Type = typename AnotherImpl<sizeof...(Types) - 1, 1>::Type;
  };

全:

template <class... Types> struct My {

  template <int... Values> struct Inner {
    constexpr std::array<int, sizeof...(Values)> to_array() {
      return std::array<int, sizeof...(Values)>{Values...};
    }
  };

  template <int size, int... Values> struct AnotherImpl {
    using Type = typename AnotherImpl<size - 1, Values..., 0>::Type;
  };

  template <int... Values> struct AnotherImpl<0, Values...> {
    using Type = Inner<Values...>;
  };

  template <class T> struct Another {
    using Type = typename AnotherImpl<sizeof...(Types) - 1, 1>::Type;
  };
};

auto main() -> int {
  My<int, float, char>::Another<int>::Type s;

  auto a = s.to_array();

  for (auto e : a) {
    cout << e << " ";
  }
  cout << endl;

  return 0;
}

打印:

1 0 0

这是你想要的吗?

答案 1 :(得分:1)

我认为你要找的是这样的。

#include <array>
#include <cstddef>
#include <iostream>
#include <type_traits>

template <typename NeedleT, typename... HaystackTs>
constexpr auto get_type_index_mask() noexcept
{
  constexpr auto N = sizeof...(HaystackTs);
  return std::array<bool, N> {
    (std::is_same<NeedleT, HaystackTs>::value)...
  };
}

template <typename T, std::size_t N>
constexpr std::size_t ffs(const std::array<T, N>& array) noexcept
{
  for (auto i = std::size_t {}; i < N; ++i)
    {
      if (array[i])
        return i;
    }
  return N;
}

int
main()
{
  const auto mask = get_type_index_mask<float, bool, int, float, double, char>();
  for (const auto& bit : mask)
    std::cout << bit;
  std::cout << "\n";
  std::cout << "float has index " << ffs(mask) << "\n";
}

输出:

00100
float has index 2

神奇发生在参数包扩展

(std::is_same<NeedleT, HaystackTs>::value)...

您在HaystackTs中针对NeedleT测试每种类型。如果您想考虑std::decayconst int相同的类型,则可能需要将int应用于任一类型。