模板成员变量取决于规则

use*_*616 2 c++ templates variadic-templates c++17

在以下代码中:

#include <iostream>
#include <tuple>

template<typename T>
struct Container
{
  std::string id;
  T value;

  Container(std::string id, T value) : id(id), value(value) {}
};

template<typename... T>
struct ElementCodec
{
  std::tuple<T...> values;

  ElementCodec(T... args) : values(args...) {}
};

template<typename... T> ElementCodec(T...) -> ElementCodec<T...>;

int main()
{
  ElementCodec a { int { 5 }, double { 3. }, Container { "52", 7 } };
  auto [x, y, container] = a.values;

  std::cout << x << ", " << y << ", " << container.value << '\n';

}
Run Code Online (Sandbox Code Playgroud)

在对给定代码进行特殊化之后,元组values为类型std::tuple<int, double, Container<int>>。我想做的就是将其分解为存储在容器中的类型,因此不需要std::tuple<int, double, int>通过进行访问container.value

在c ++ 17中可以做到吗?我已经在这个问题上停留了一段时间了,而且真的找不到任何资源。

Bar*_*rry 7

您可以Container<T>使用辅助函数将s 解开:

template <typename T> T unwrap(T value)        { return value; }
template <typename T> T unwrap(Container<T> c) { return c.value; }

template <typename T> using unwrap_t = decltype(unwrap(std::declval<T>()));
Run Code Online (Sandbox Code Playgroud)

然后相应地调整您的模板和扣除指南:

template <typename... T>
struct ElementCodec
{
  std::tuple<T...> values;

  template <typename... Us>
  ElementCodec(Us... args) : values(unwrap(args)...) {}
};

template<typename... T>
ElementCodec(T...) -> ElementCodec<unwrap_t<T>...>;
Run Code Online (Sandbox Code Playgroud)

上面的方法在gcc上不起作用(请参阅此答案),您可以使用约束对其进行修复:

template <typename... Us,
  std::enable_if_t<std::is_constructible_v<
    std::tuple<T...>, unwrap_t<Us>...
    >, int> = 0>
ElementCodec(Us... args) : values(unwrap(args)...) {}
Run Code Online (Sandbox Code Playgroud)