将数组与可变模板相关联

Associating an array with a variadic template

本文关键字:关联 数组      更新时间:2023-10-16

我现在正在学习一些关于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,在Types...Type的位置上有一个,在其他地方有零——在这里我迷路了。我不知道如何进行

如果我朝着错误的方向前进,我希望有人能给我一个如何做到这一点的提示。

我想你想要的是这样的东西。

#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进行测试。如果您想将const intint视为同一类型,则可能需要将std::decay应用于任一类型。

  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

这是你想要的吗?