【问题标题】:How to convert between different instantiations of the same variadic template?如何在同一可变参数模板的不同实例之间进行转换?
【发布时间】:2016-09-26 20:27:44
【问题描述】:

假设我们有一个数据结构 Foo 来维护一组元素。应该可以根据需要将属性与元素相关联。属性应分别存储在一个单独的向量中。我们通过可变参数模板来实现这一点:

#include <vector>

template <typename ...Attrs>
struct Foo : public Attrs... {
  Foo(int n = 0) {
    using PackExpansionT = int[];
    PackExpansionT{0, (Attrs::values.resize(n), 0)...};
  }
};

struct AttrA { std::vector<int>    values; };
struct AttrB { std::vector<float>  values; };
struct AttrC { std::vector<double> values; };

int main() {
  Foo<AttrA, AttrB> foo; // Maintains set of elements with two attributes each.
};

现在,我想要一个具有以下语义的转换运算符:

  Foo<AttrB, AttrC> bar = foo; // bar.AttrB::values should be a copy of foo.AttrB::values.

这只是一个例子。通常,转换运算符应该能够将具有任意属性的Foo 转换为具有任意属性的另一个 Foo。应该复制与Foos 关联的属性。与两者无关的属性可以保留默认值。但是,我不知道如何实现它。

  template <typename ...OthersAttrs>
  operator Foo<OthersAttrs...>() const {
    // ...?
  }

【问题讨论】:

  • 你如何处理与目标相关但与源无关的属性?
  • 暂时不重要。也许它们的值被设置为一些默认值,也许它们的值只是未定义的。
  • @user1494080 这很重要:在从foo 复制初始化之后,您希望bar 是什么?
  • @Barry Well...正如我所说:应该复制与两者关联的属性。仅与 bar 关联的属性可能未定义或设置为默认值。我不在乎。对我来说重要的是与两者关联的所有属性都被复制。

标签: c++ c++11 type-conversion variadic-templates


【解决方案1】:

我们可以做出一堆独立的决定。首先,让我们添加一个构造函数,以便我们可以根据其属性成分构造Foo

Foo(Attrs const&... attrs)
: Attrs(attrs)...
{ }

接下来,对于Others 中的每个属性,如果可能,我们会将this 向下转换为适当的类型,否则返回默认构造的类型:

template <typename... Others>
operator Foo<Others...>() const {
    return {get_attr<Others>(this)...};
}

地点:

template <class T>
T const& get_attr(T const* v) const {
    return *v;
}

template <class T>
T get_attr(...) const {
    return T{};
}

【讨论】:

    【解决方案2】:

    我能想到的大纲:

    template <typename ...OthersAttrs>
    operator Foo<OthersAttrs...>() const
    {
        Foo<OthersAttrs...> rv(GetNSomehow());
        (int[]){(CopyAttr<Attrs>(&rv), 0)...};
        return rv;
    }
    
    template<typename Attr>
    void CopyAttr(Attr *rv) const // Overload A
    {
        rv->values = ((const Attr*)this)->values;
    }
    
    template<typename Attr>
    void CopyAttr(...) const // Overload B
    {
    
    }
    

    这里的诀窍是逐个属性。
    如果rv 具有该属性,则将选择第一个重载并将其复制。
    否则将选择第二个重载,它什么都不做。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-15
      • 2019-02-07
      • 1970-01-01
      • 2016-07-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多