c++ - 基于位置的包中的特定类型

标签 c++ templates c++14 variadic-templates c++17

take_from_args<foo<int, bool, char, float>, 0,2>::type是要

foo<int, char>基于位置 0 和 2。实现很简单:

template <typename Class, std::size_t... Positions>
struct take_from_args;

template <template <typename...> class P, typename... Ts, std::size_t... Is>
struct take_from_args<P<Ts...>, Is...> {
    using type = P<std::tuple_element_t<Is, std::tuple<Ts...>>...>; 
};

现在,让我们尝试将其应用于此类:

template <int V, bool B, typename... Args>
struct bar {};

问题是bar的int和bool参数, 所以它不能传递到 take_from_args .所以让我们定义:

template <int V, bool B>
struct bar_h {
    template <typename... Args>
    using templ = bar<V, B, Args...>;   
};

不幸的是,take_from_args<bar_h<5, true>::templ<int, bool, char, float>, 0,2>::type不会编译。如何重新定义 take_from_args这样它就可以像bar这样的模板类?

我的整个代码:

#include <tuple>

template <typename Class, std::size_t... Positions> struct take_from_args;

template <template <typename...> class P, typename... Ts, std::size_t... Is>
struct take_from_args<P<Ts...>, Is...> {
    using type = P<std::tuple_element_t<Is, std::tuple<Ts...>>...>; 
};


// Testing
template <typename... Args>
struct foo {};

template <int V, bool B, typename... Args>
struct bar {};

template <int V, bool B>
struct bar_h {
    template <typename... Args>
    using templ = bar<V, B, Args...>;   
};

int main() {
    static_assert(std::is_same<
        take_from_args<foo<int, bool, char, float>, 0,2>::type,
        foo<int, char>>::value);
//  static_assert(std::is_same<
//      take_from_args<bar_h<5, true>::templ<int, bool, char, float>, 0,2>::type,
//      bar<5, true, int, char>>::value);
}

最佳答案

您使用 bar_h 的解决方法不起作用,因为 bar_h<5, true>::templ<int, bool, char, float>只是 bar<5, true, int, bool, char, float>别名 :

static_assert(// compiles without error
  std::is_same_v<
    bar_h<5, true>::templ<int, bool, char, float>,
    bar<5, true, int, bool, char, float>
  >
);

我看到两个选项:

1。避免在 `bar` 中使用非类型模板参数

编辑:当您在 your answer 中遵循此方法时,但我经历了issues with clang : 这是一个修改版本 works for me使用 GCC 7.2 和 Clang 5.0。

template<auto...> struct Vals {};

template<class T>
struct HasVals : std::false_type {};

template<auto... Vs>
struct HasVals<Vals<Vs...>> : std::true_type {};

template<class T, size_t... is>
struct take_from_args;

template<template<class...> class P, class... Ts, size_t... is>
struct take_from_args<P<Ts...>, is...> {
// convention: pass-through first argument if it `HasVals`
  using Vs = std::tuple_element_t<0, std::tuple<Ts...>>;
  using type = std::conditional_t<
    HasVals<Vs>::value,
    P<Vs, std::tuple_element_t<1u+is, std::tuple<Ts...>>...>,
    P<std::tuple_element_t<is, std::tuple<Ts...>>...>
  >;
};

// Testing
template<class Vs, class... Args>
struct bar;

template<int v, bool b, class... Args>
struct bar<Vals<v, b>, Args...> {
    static constexpr int value = v;
    static constexpr bool truth = b;
};

2. 为 `take_from_args` 提供更多特化

既然你特别要求后者,这里有一个例子:

// there could be 1 value(s) at the beginning...
template<
  template<auto, auto, typename...> class P,
  auto v0, class... Ts, std::size_t... is
> struct take_from_args<P<v0, Ts...>, is...> {
  using type = P<v0, std::tuple_element_t<is, std::tuple<Ts...>>...>;
};

// ... 2 ...
template<
  template<auto, auto, typename...> class P,
  auto v0, auto v1, class... Ts, std::size_t... is
> struct take_from_args<P<v0, v1, Ts...>, is...> {
  using type = P<v0, v1, std::tuple_element_t<is, std::tuple<Ts...>>...>;
};

// ... 3 ... and more?
template<
  template<auto, auto, typename...> class P,
  auto v0, auto v1, auto v2, class... Ts, std::size_t... is
> struct take_from_args<P<v0, v1, v2, Ts...>, is...> {
  using type = P<v0, v1, v2, std::tuple_element_t<is, std::tuple<Ts...>>...>;
};

不幸的是,我没有成功使用 auto...用于推导前导模板参数。

关于c++ - 基于位置的包中的特定类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46867004/

相关文章:

C++ unordered_map 使用自定义类类型作为键

c++ - 在 C++ 中一般将 "optional"字段封装在结构中的最佳方法?

c++ - 仅使用 XCB 创建 OpenGL 上下文

c++ - 为什么 boost::adaptors::filtered 的输出没有名为 size 的成员?

c++ - 重载运算符的显式特化 '<<'(左移)

c++ - 将 lambda 作为构造函数参数传递

c++ - 将 std::condition_variable 与 std::timed_mutex 一起使用

c++ - 将adt_proxy类型替换为值类型时的Boost fusion 错误

c++ - 在生产中使用 Address Sanitizer 或其他未定义的行为 sanitizer ?

c++ - OpenCV 数据类型的类型特征