1

我有两组遵循以下模式的 mixin 基类

// base class taking one contructor argument
struct OneArgBase
{
  const double x;

  template<typename T>
  OneArgBase(const T & t) :
    x(t.x)
  {}
};

// base class taking two constructor arguments
struct TwoArgBase
{
  const double y;

  template<typename T, typename U>
  TwoArgBase(const T & t, const U & u) :
    y(t.y + u.y)
  {}
 };

从这些基类中,我派生了两组 mixin 类

template<typename ... Mixins>
struct OneArgMix : Mixins...
{
  template<typename T>
  OneArgsMix(const T & t) :
    Mixins(t)...
  {}
};

template<typename ... Mixins>
struct TwoArgMix : Mixins...
{
  template<typename T, typename U>
  TwoArgsMix(const T & t, const U & u) :
    Mixins(t, u)...
  {}
};

我现在面临的问题是,我想将遵循 OneArgBase 模式的类传递给 TwoArgMix

using Mix = TwoArgMix<TwoArgBase, OneArgBase>;

template<typename ... Mixins>
struct TwoArgMix : Mixins...
{
  template<typename T, typename U>
  TwoArgsMix(const T & t, const U & u) :
    Mixins(t, u)... // if Mixins is TwoArgBase
    Mixins(t)... // if Mixins is OneArgBase
  {}
};

但不知道两个如何编写 TwoArgMix 的构造函数,如果只将第一个模板参数传递给遵循 OneArgMix 模式的 Mixin 基类。如果可能的话,我想避免向 OneArgMix 构造函数写入虚拟参数,因为 OneArgMix 也需要这些类。

4

3 回答 3

3

编程中的所有问题都可以通过添加另一层间接来解决。

如果第二个参数不可构造,我们需要有条件地忽略它。一种方法是将每个 mixin 包装在另一种有条件地忽略其第二个参数的类型中:

template <typename M>
struct WrappedMixin : M
{
    template <typename T, typename U>
    WrappedMixin(T const& t, U const& u)
       : WrappedMixin(t, u, std::is_constructible<M, T const&, U const&>{})
    { }

private:
    template <typename T, typename U>
    WrappedMixin(T const& t, U const& u, std::true_type /* yes, use both */)
      : M(t, u)
    { }

    template <typename T, typename U>
    WrappedMixin(T const& t, U const&, std::false_type /* no, just one */)
      : M(t)
    { }
};

现在,我们的主要构造函数很简单:我们只是从被包装的构造函数继承:

template<typename ... Mixins>
struct TwoArgMix : WrappedMixin<Mixins>...
{
  template<typename T, typename U>
  TwoArgsMix(const T & t, const U & u)
    : WrappedMixin<Mixins>(t, u)...
  { }
};
于 2020-01-21T10:29:24.733 回答
2

使用工厂,您可能会执行以下操作:

template <typename> struct Tag{};

template<typename T, typename U>
OneArgBase Create(Tag<OneArgBase>, const T& t, const U&)
{
    return OneArgBase(t);
}

template<typename T, typename U>
TwoArgBase Create(Tag<TwoArgBase>, const T& t, const U& u)
{
    return TwoArgBase(t, u);
}

template<typename ... Mixins>
struct TwoArgsMix : Mixins...
{
  template<typename T, typename U>
  TwoArgsMix(const T & t, const U & u) :
    Mixins(Create(Tag<Mixins>{}, t, u))...
  {}
};

演示

于 2020-01-21T10:06:26.143 回答
0

您可以尝试使用部分指定的模板。

就像是:

template<typename twoarg>
struct TwoArgMix<twoarg, OneArgBase>: ...

它将 OneArgBase 作为第二个模板参数的具体实现。

于 2020-01-21T10:06:54.653 回答