比较可变参数模板

发布于 2024-11-18 22:57:25 字数 439 浏览 2 评论 0原文

如果我有两个可变参数模板参数 AB,如何在编译时确保 A 的所有成员的类型> 也是 B 子集的类型(顺序相同)?

人为的例子:

template<typename...A>
struct Foo {
  template<typename...B>
  static void bar()
  {
  }
}

...

Foo<Apple, Orange>:: template bar<Apple, Orange, Grape>(); // this compiles
Foo<Apple, Orange>:: template bar<Orange, Grape>(); // this doesn't

If I have two variadic template arguments, A and B, how can I ensure at compile-time that the types of all of the members of A are also the types of a subset of B (in the same order)?

Contrived example:

template<typename...A>
struct Foo {
  template<typename...B>
  static void bar()
  {
  }
}

...

Foo<Apple, Orange>:: template bar<Apple, Orange, Grape>(); // this compiles
Foo<Apple, Orange>:: template bar<Orange, Grape>(); // this doesn't

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

趁微风不噪 2024-11-25 22:57:25

对于一般子集,我不知道,但如果您可以保证 B 的形式为 A..., More...,那么这可能会这样做:

#include <functional>
#include <tuple>

template <typename ...A>
struct var_equal : std::false_type { };

template <typename A1, typename ...Aother, typename B1, typename ...Bother>
struct var_equal<std::tuple<A1, Aother...>, std::tuple<B1, Bother...>>
{
  static const bool value = std::is_same<A1, B1>::value && var_equal<std::tuple<Aother...>, std::tuple<Bother...>>::value;
};

template <typename ...B>
struct var_equal<std::tuple<>, std::tuple<B...>> : std::true_type { };


template<typename...A>
struct Foo {
  template<typename...B>
  static void bar()
  {
    static_assert(var_equal<std::tuple<A...>, std::tuple<B...>>::value, "Hello");
  }
};

(抱歉,var_equal 是一个糟糕的名称。它应该被称为更合适的名称,例如 initial_equal。)


更新: 这是一般解决方案, Luc Danton 详细制定了​​(请参阅此处查看其精美样式的代码):

#include <type_traits>
#include <tuple>

template <typename Sub, typename Super>
struct subset_of : std::false_type {};

template<typename Same, typename... AOther, typename... BOther>
struct subset_of<std::tuple<Same, AOther...>, std::tuple<Same, BOther...>>
: subset_of<
    std::tuple<AOther...>
    , std::tuple<BOther...>
> {};

template<typename ADifferent, typename BDifferent, typename... AOther, typename... BOther>
struct subset_of<std::tuple<ADifferent, AOther...>, std::tuple<BDifferent, BOther...>>
: subset_of<
    std::tuple<ADifferent, AOther...>
    , std::tuple<BOther...>
> {};

template<typename... B>
struct subset_of<std::tuple<>, std::tuple<B...>>: std::true_type {};

template<typename... A>
struct Foo {
    template<typename... B>
    static void bar()
    {
        static_assert(subset_of<std::tuple<A...>, std::tuple<B...>>::value, "Hello");
    }
};

测试用例:

struct Apple{}; struct Orange{}; struct Grape{};

int main()
{
    Foo<Apple, Orange>::bar<Apple, Orange, Grape>();               // this compiles
    Foo<Apple, Orange>::bar<Grape, Apple, Grape, Orange, Grape>(); // this also compiles
    Foo<Apple, Orange>::bar<Orange, Grape>();                      // this doesn't
}

For a general subset I don't know, but if you can guarantee that B is of the form A..., More..., then this may do:

#include <functional>
#include <tuple>

template <typename ...A>
struct var_equal : std::false_type { };

template <typename A1, typename ...Aother, typename B1, typename ...Bother>
struct var_equal<std::tuple<A1, Aother...>, std::tuple<B1, Bother...>>
{
  static const bool value = std::is_same<A1, B1>::value && var_equal<std::tuple<Aother...>, std::tuple<Bother...>>::value;
};

template <typename ...B>
struct var_equal<std::tuple<>, std::tuple<B...>> : std::true_type { };


template<typename...A>
struct Foo {
  template<typename...B>
  static void bar()
  {
    static_assert(var_equal<std::tuple<A...>, std::tuple<B...>>::value, "Hello");
  }
};

(Sorry, var_equal is a terrible name. It should be called something more appropriate, like initial_equal.)


Update: Here is the general solution, worked out in detail by Luc Danton (see here for his beautifully styled code):

#include <type_traits>
#include <tuple>

template <typename Sub, typename Super>
struct subset_of : std::false_type {};

template<typename Same, typename... AOther, typename... BOther>
struct subset_of<std::tuple<Same, AOther...>, std::tuple<Same, BOther...>>
: subset_of<
    std::tuple<AOther...>
    , std::tuple<BOther...>
> {};

template<typename ADifferent, typename BDifferent, typename... AOther, typename... BOther>
struct subset_of<std::tuple<ADifferent, AOther...>, std::tuple<BDifferent, BOther...>>
: subset_of<
    std::tuple<ADifferent, AOther...>
    , std::tuple<BOther...>
> {};

template<typename... B>
struct subset_of<std::tuple<>, std::tuple<B...>>: std::true_type {};

template<typename... A>
struct Foo {
    template<typename... B>
    static void bar()
    {
        static_assert(subset_of<std::tuple<A...>, std::tuple<B...>>::value, "Hello");
    }
};

Test case:

struct Apple{}; struct Orange{}; struct Grape{};

int main()
{
    Foo<Apple, Orange>::bar<Apple, Orange, Grape>();               // this compiles
    Foo<Apple, Orange>::bar<Grape, Apple, Grape, Orange, Grape>(); // this also compiles
    Foo<Apple, Orange>::bar<Orange, Grape>();                      // this doesn't
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文