在参数包中查找类型

use*_*108 6 c++ c++11

我正在尝试A在参数包中找到类型:

template <int I, typename A, typename B, typename ...C>
struct index_of
{
  static constexpr int const value =
    std::is_same<A, B>::value ? I : index_of<I + 1, A, C...>::value;
};

template <int I, typename A, typename B>
struct index_of<I, A, B>
{
  static constexpr int const value =
    std::is_same<A, B>::value ? I : -1;
};
Run Code Online (Sandbox Code Playgroud)

这似乎工作,但我无法消除nontype参数I,我想成为默认参数,但由于最后的参数包,不能这样做.如何消除/隐藏I,因此元功能变得更加用户友好?

a.l*_*ram 6

您可以在命名空间中隐藏此实现,并使用另一个使用默认参数示例调用您的实现的类:

namespace detail
{
    // your code as it is in the question
}

template <typename A, typename... B>
struct index_of
{
    static int const value = detail::index_of<0, A, B...>::value;
};
Run Code Online (Sandbox Code Playgroud)

编辑

在他的评论中,DyP提出了一种I使用别名进行默认的简单方法

template <typename A, typename... B>
using index_of = detail::index_of<0, A, B...>;
Run Code Online (Sandbox Code Playgroud)

  • 在C++ 11中,您甚至可以使用别名模板. (2认同)

dyp*_*dyp 3

template <typename A, typename B, typename... C>
struct index_of
{
  static constexpr int const value =
    std::is_same<A, B>{}
    ? 0
    : (index_of<A, C...>::value >= 0) ? 1+index_of<A, C...>::value : -1;
};

template <typename A, typename B>
struct index_of<A, B>
{
  static constexpr int const value = std::is_same<A, B>{} -1;
};
Run Code Online (Sandbox Code Playgroud)

请注意,使用从到 的std::is_same<A, B>{} -1转换。boolint


更好地源自integral_constant

template <typename A, typename B, typename... C>
struct index_of
  : std::integral_constant
    < int,
        std::is_same<A, B>{}
      ? 0
      : (index_of<A, C...>{} == -1 ? -1 : 1+index_of<A, C...>{})
    >
{};

template <typename A, typename B>
struct index_of<A, B>
  : std::integral_constant < int, std::is_same<A, B>{} -1 >
{};
Run Code Online (Sandbox Code Playgroud)

如果您不需要返回-1以防找不到类型:(如果有人知道如何static_assert在此处合并一个漂亮的诊断消息,我将不胜感激评论/编辑)

template <typename A, typename B, typename... C>
struct index_of
  : std::integral_constant < std::size_t,
                             std::is_same<A, B>{} ? 0 : 1+index_of<A, C...>{} >
{};

template <typename A, typename B>
struct index_of<A, B>
  : std::integral_constant<std::size_t, 0>
{
    constexpr operator std::size_t() const
    {
        return   std::is_same<A, B>{}
               ? 0
               : throw std::invalid_argument("Type not found!");
    }
};
Run Code Online (Sandbox Code Playgroud)