对于单元测试,我编写了一个类
ScopeSet
,它更改当前范围内的变量值,并在范围结束时恢复原始值。
使用示例:
int i = 1;
double d = 2.;
{
auto _ = ScopeSet( i, 10, d, 20. );
assert( i == 10 );
assert( d == 20. );
}
assert( i == 1 );
assert( d == 2. );
我已经完成了课程,除了演绎指南。
ScopeSet
采用可变数量的 variable-value
对。
到目前为止我已经手写了最多三对的推演指南
template< typename T0, typename U0 > ScopeSet( T0 &, U0 ) -> ScopeSet< T0 >;
template< typename T0, typename U0, typename T1, typename U1 > ScopeSet( T0 &, U0, T1 &, U1 ) -> ScopeSet< T0, T1 >;
template< typename T0, typename U0, typename T1, typename U1, typename T2, typename U2 > ScopeSet( T0 &, U0, T1 &, U1, T2 &, U2 ) -> ScopeSet< T0, T1, T2 >;
我的问题是,如何编写适用于可变数量对的演绎指南?
我无法提出直接推导指南,但能够使用类型包装器类型和额外的
ScopeSet
部分专业化来使其工作:
template <typename... Ts>
struct TypeWrapper {};
template <typename... Ts>
struct GetType
{
template <std::size_t I>
using Type = decltype(std::get<I>(std::declval<std::tuple<Ts...>>()));
};
template <typename... Ts, std::size_t... Is>
auto types_skip_odd(std::index_sequence<Is...>)
{
return TypeWrapper<std::remove_reference_t<typename GetType<Ts...>::Type<Is * 2>>...>();
}
template <typename... Ts>
auto even_types()
{
return types_skip_odd<Ts...>(std::make_index_sequence<sizeof...(Ts) / 2>());
}
template <typename... Ts>
struct ScopeSet<TypeWrapper<Ts...>> : ScopeSet<Ts...>
{
using ScopeSet<Ts...>::ScopeSet;
};
template <typename... Ts>
ScopeSet(Ts...) -> ScopeSet<decltype(even_types<Ts...>())>;
基本概念是让
ScopeSet(int&, int, double&, double)
推导出ScopeSet<TypeWrapper<int, double>>
并使ScopeSet<TypeWrapper<Ts...>>
继承ScopeSet<Ts...>
。
这样,
auto _ = ScopeSet( i, 10, d, 20. );
将推论为ScopeSet<TypeWrapper<int, double>>
,然后其行为将与ScopeSet<int, double>
完全相同。