PeW*_*eWe 9 c++ parameters templates pack variadic-templates
我有一个struct C
初始化的可变数量的实例struct A
和struct B
.例如:
struct A
{};
struct B
{};
struct C
{
C(A&& o1, B&& p1, A&& o2)
{}
C(A&& o1, B&& p1, A&& o2, B&& p2, A&& o3)
{}
C(A&& o1, B&& p1, A&& o2, B&& p2, A&& o3, B&& p3, A&& o4)
{}
C(A&& o1, B&& p1, A&& o2, B&& p2, A&& o3, B&& p3, A&& o4, B&&p4, A&& o5)
{}
};
Run Code Online (Sandbox Code Playgroud)
因此,我不想提供具有不同数量参数的多个ctor,而是希望找到一些通用的东西.但是,ctor参数的数量总是增加两个参数:B&&
和A&&
.这可以使用参数包完成.或者是没有针对每个参数实现的另一个解决方案?
目标应该是struct C
可以像下面的例子那样构建:
C c1 = { A(), B(), A() };
C c2 = { A(), B(), A(), B(), A(), B(), A() };
Run Code Online (Sandbox Code Playgroud)
等等
您可以使用可变参数模板和SFINAE来仅启用类型参数满足您(或任意)条件的构造函数.
#include <type_traits>
struct A {};
struct B {};
Run Code Online (Sandbox Code Playgroud)
你需要type_traits
为std::false_type
和std::true_type
.
该alternates
模板是关键.我们的目标是使alternates<X, Y, T1, T2, T3, ..., Tn>
继承std::true_type
,当且仅当T1
,... Tn
列表交替X
和Y
.默认选择(正下方)是没有的,但我们专门匹配的情况.
template <typename X, typename Y, typename... Ts>
struct alternates : std::false_type {};
Run Code Online (Sandbox Code Playgroud)
我选择使这个模板比你的要求更通用,并允许alternates<X, Y>
继承true_type
.空列表满足其所有元素交替的数学要求.这将是下面递归定义的一个很好的权宜之计.
template <typename X, typename Y>
struct alternates<X, Y> : std::true_type {};
Run Code Online (Sandbox Code Playgroud)
的任何其他列表alternates<X, Y, Ts...>
交替当且仅当Ts...
减去第一元件交替Y
和X
(Y
第一!).
template <typename X, typename Y, typename... Ts>
struct alternates<X, Y, X, Ts...>
: alternates<Y, X, Ts...> {};
struct C
{
Run Code Online (Sandbox Code Playgroud)
我们将构造函数定义为首先获取参数包的模板(将推导出类型,不需要在调用时指定),并且它具有用于SFINAE目的的默认模板参数.如果无法基于参数包计算默认参数,则构造函数将不存在.我添加了关于我从示例中假设的对数的额外条件.
template<typename... Ts,
typename = typename std::enable_if<
sizeof...(Ts) % 2 == 1 &&
sizeof...(Ts) >= 3 && // did you imply this?
alternates<A, B, Ts...>::value
>::type>
C(Ts&&...);
};
Run Code Online (Sandbox Code Playgroud)
SFINAE的工作方式是std::enable_if
只定义std::enable_if<condition, T>::type
(::type
部分)if是否condition
为真.这可以是在编译时可计算的任何布尔表达式.如果它是假的,::type
那么最后说的是替换失败,并且你试图使用它的重载(例如C{A(), A(), A()}
)将不会被定义.
您可以测试以下示例是否按预期工作.评论出来的那些预计不起作用.
int main() {
C c1 { A(), B(), A() };
C c2 { A(), B(), A(), B(), A(), B(), A() };
// C c3 {}; // I assumed you need at least 2
// C c4 { A(), B(), A(), A() }; // A, A doesn't alternate
// C c5 { B(), A(), B() }; // B, A, B not allowed
// C c6 { A(), B(), A(), B() }; // A, B, A, B doesn't pair
}
Run Code Online (Sandbox Code Playgroud)
我想你可以使用模板委托构造函数
事情如下
#include <utility>
struct A {};
struct B {};
struct C
{
C (A &&)
{ }
template <typename ... Ts>
C (A &&, B &&, Ts && ... ts) : C(std::forward<Ts>(ts)...)
{ }
};
int main()
{
C(A{});
C(A{}, B{}, A{});
C(A{}, B{}, A{}, B{}, A{});
C(A{}, B{}, A{}, B{}, A{}, B{}, A{});
}
Run Code Online (Sandbox Code Playgroud)
如果你需要至少三个元素(因此C(A{})
至少没有C(A{}, B{}, A{})
),那么not-template构造函数就变成了
C (A &&, B &&, A&&)
{ }
Run Code Online (Sandbox Code Playgroud)