具有可变数量模板参数的 CTAD

问题描述 投票:0回答:1

对于单元测试,我编写了一个类

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 >;

我的问题是,如何编写适用于可变数量对的演绎指南?

c++ variadic-templates ctad
1个回答
0
投票

我无法提出直接推导指南,但能够使用类型包装器类型和额外的

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>
完全相同。

© www.soinside.com 2019 - 2024. All rights reserved.