使用C ++模板匹配类型列表中的类型

问题描述 投票:0回答:1

我需要在编译时使用C ++模板匹配类型列表中的类型。这是我的代码,但它编译成错误。知道我怎么解决它?

template <typename T, typename X, typename... Rs>
struct match
{
    using test = typename std::conditional<std::is_same<T, X>::value, X, bool>::type;
    using more = typename match<T, Rs...>::type;
    using type = typename std::conditional<std::is_same<test, bool>::value, more, test>::type;
};

template <typename T>
struct match<T, bool>
{
    using type = bool;
};

match<int, int, float>::type x;

错误是:

1.cpp:99:45: error: wrong number of template arguments (1, should be at least 2)
  using more = typename match<T, Rs...>::type;

                                         ^
c++ templates variadic-templates
1个回答
1
投票

您应该添加一个部分特化来处理具有两个模板参数的情况,否则more的实例化将导致match的实例化,其中包含一个模板参数,因此会发生错误。你的match<T, bool>只处理最后一个参数是bool的情况,你应该声明它,例如,

template <typename T, typename X>
struct match<T, X>
{
    using type = typename std::conditional<std::is_same<T, X>::value, X, bool>::type;
};

另外,我不知道test有什么用。我认为在more的定义中直接使用type就足够了:

template <typename T, typename X, typename... Rs>
struct match
{
    using more = typename match<T, Rs...>::type;
    using type = typename std::conditional<std::is_same<T, X>::value, X, more>::type;
};

这仍然不是最好的解决方案,因为它会导致more的实例化,即使T匹配X(在这种情况下,我们可以断言match::type是没有X实例化的more)。为避免不必要的实例化,您可以添加其他部分特化:

template <typename T, typename... Rs>
struct match<T, T, Rs...>
{
    using type = T;
};

使用此部分特化,主模板仅匹配T不是X的情况,因此您可以进一步简化主模板

template <typename T, typename X, typename... Rs>
struct match
{
    using type = typename match<T, Rs...>::type;
};

为了完整起见,最终的解决方案是:

#include <type_traits>

template <typename T, typename X, typename... Rs>
struct match
{
    using type = typename match<T, Rs...>::type;
};

template <typename T, typename... Rs>
struct match<T, T, Rs...>
{
    using type = T;
};

template <typename T, typename X>
struct match<T, X>
{
    using type = typename std::conditional<std::is_same<T, X>::value, X, bool>::type;
};

static_assert(std::is_same<int, match<int, int, float>::type>::value);
© www.soinside.com 2019 - 2024. All rights reserved.