根据参数个数调用 mixin base 类 的构造函数
Call constructor of mixin base classes based on number of arguments
我有两套 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 base 类 的第一个模板参数。
如果可能的话,我想避免向 OneArgMix 构造函数写入伪参数,
因为 OneArgMix 也需要这些 类。
对于 factory,您可能会执行以下操作:
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))...
{}
};
您可以尝试使用部分指定的模板。
类似于:
template<typename twoarg>
struct TwoArgMix<twoarg, OneArgBase>: ...
以OneArgBase为第二个模板参数具体实现
编程中的所有问题都可以通过添加另一层间接来解决。
如果第二个参数不可构建,我们需要有条件地忽略它。一种方法是将每个 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)...
{ }
};
我有两套 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 base 类 的第一个模板参数。 如果可能的话,我想避免向 OneArgMix 构造函数写入伪参数, 因为 OneArgMix 也需要这些 类。
对于 factory,您可能会执行以下操作:
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))...
{}
};
您可以尝试使用部分指定的模板。
类似于:
template<typename twoarg>
struct TwoArgMix<twoarg, OneArgBase>: ...
以OneArgBase为第二个模板参数具体实现
编程中的所有问题都可以通过添加另一层间接来解决。
如果第二个参数不可构建,我们需要有条件地忽略它。一种方法是将每个 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)...
{ }
};