【问题标题】:Template member variables depending on rules模板成员变量取决于规则
【发布时间】:2019-04-17 14:46:15
【问题描述】:

在以下代码中:

#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';

}

在给定代码特化之后,元组values 的类型为std::tuple&lt;int, double, Container&lt;int&gt;&gt;。我想做的是将其衰减为存储在容器中的类型,因此std::tuple&lt;int, double, int&gt; 不需要通过container.value 进行访问。

这可以在 c++17 中实现吗?我已经被这个问题困扰了一段时间,并且找不到任何关于此的资源。

【问题讨论】:

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


    【解决方案1】:

    您可以使用辅助函数打开 Container&lt;T&gt;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>()));
    

    然后相应地调整你的模板和演绎指南:

    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>...>;
    

    以上在 gcc 上不起作用(参见this answer),您可以通过约束来修复它:

    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)...) {}
    

    【讨论】:

    • 谢谢,这行得通。但是,我真的不明白你在 gcc-bug-fix 上做什么。你能详细说明一下吗?
    • 它叫做sfinae。这真是个兔子洞。搜索std::enable_if
    • @user3520616 阅读链接的答案,并考虑约束对相关候选人的影响。
    猜你喜欢
    • 2017-02-22
    • 2017-01-16
    • 1970-01-01
    • 2017-10-18
    • 1970-01-01
    • 2015-10-04
    • 1970-01-01
    • 1970-01-01
    • 2021-07-25
    相关资源
    最近更新 更多