C++模板元编程 记录
常犯的小错误:
- 没有
std::is_same_t,只有std::is_same_v - 在模板类定义
value时记得加typename:using value = typename ...
Policy定义:
struct AccPolicy
{
struct AccuTypeCate
{
struct Add;
struct Mul;
};
using Accu = AccuTypeCate::Add;
struct IsAveValueCate;
static constexpr bool IsAve = false;
struct ValueTypeCate;
using Value = float;
using MajorClass = AccPolicy;
};
这里每一个struct都起到命名空间的作用,用于容纳一系列类型(类型即配置)。
MajorClass和MinorClass这两个名字将贯穿所有代码,这是一种约定:MajorClass表示了用于一个用途的配置,MinorClass表示该用途下对某个方面的细分配置。
如果我们接受这套约定,下面的元函数代码就有通用性了。
类型容器:
template <typename... TPolicies>
struct PolicyContainer;
MajorFilter_元函数过滤类型容器中的类型,使得它们有相同的MajorClass。这里写得复杂了点,可以不需要Filter_:
template <typename TCurPolicy, bool insert, typename... Filtered>
struct Filter_
{
using value = typename PolicyContainer<Filtered...>;
};
template <typename TCurPolicy, typename... Filtered>
struct Filter_<TCurPolicy, true, Filtered...>
{
using value = typename PolicyContainer<Filtered..., TCurPolicy>;
};
template <typename TPolicyContainer, typename TMajorClass, typename... TPolicies>
struct MajorFilter_
{
using type = typename TPolicyContainer;
};
template <typename... Filtered, typename TMajorClass, typename TCurPolicy, typename... TPolicies>
struct MajorFilter_<PolicyContainer<Filtered...>, TMajorClass, TCurPolicy, TPolicies...>
{
constexpr static bool insert = std::is_same_v<TMajorClass, typename TCurPolicy::MajorClass>;
using type = typename MajorFilter_<typename Filter_<TCurPolicy, insert, Filtered...>::value, TMajorClass, TPolicies...>::type;
};
&运算符的元函数版本:
/* and的元函数版本 */
template <bool T, bool P>
constexpr bool AndValue = P;
template <bool P>
constexpr bool AndValue<false, P> = false;
传入MinorClass和一个类型列表,检查列表的MinorClass是否和给定的MinorClass都不同:
template <typename TMinorClass, typename... TP>
struct MinorDedup_
{
static constexpr bool value = true;
};
template <typename TMinorClass, typename TCurPolicy, typename... TP>
struct MinorDedup_<TMinorClass, TCurPolicy, TP...>
{
using TCurMirror = typename TCurPolicy::MinorClass;
constexpr static bool cur_check = !std::is_same_v<TMinorClass, TCurMirror>;
constexpr static bool value = AndValue<cur_check, MinorDedup_<TMinorClass, TP...>::value>;
};
传入Policy列表,检查MinorClass是否互不相同:
template <typename TPolicyCont>
struct MinorCheck_
{
static constexpr bool value = true;
};
template <typename TCurPolicy, typename... TP>
struct MinorCheck_<PolicyContainer<TCurPolicy, TP...>>
{
static constexpr bool cur_check = MinorDedup_<typename TCurPolicy::MinorClass, TP...>::value;
static constexpr bool value = AndValue<cur_check, MinorCheck_<PolicyContainer<TP...>>::value>;
};
传入PolicyContainer,判断容器内是否有元素:
template <typename T>
constexpr bool IsArrayEmpty = false;
template <typename... TPolicy>
constexpr bool IsArrayEmpty<PolicyContainer<TPolicy...>> = sizeof...(TPolicy) == 0;
定义Policy:
template <typename TPolicyCont>
struct PolicySelRes;
template <typename TPolicy>
struct PolicySelRes<PolicyContainer<TPolicy>> : public TPolicy
{
};
template <typename TCurPolicy, typename... TOtherPolicies>
struct PolicySelRes<PolicyContainer<TCurPolicy, TOtherPolicies...>>
: public TCurPolicy, public PolicySelRes<PolicyContainer<TOtherPolicies...>>
{
};
组合Policy,构造包含多个配置的Policy:
template <typename TMajorClass, typename TPolicyContainer>
struct Selector_;
template <typename TMajorClass, typename... TPolicies>
struct Selector_<TMajorClass, PolicyContainer<TPolicies...>>
{
using TMF = typename MajorFilter_<PolicyContainer<>,
TMajorClass,
TPolicies...>::type;
static_assert(MinorCheck_<TMF>::value, "Minor class set conflict!");
using type = typename std::conditional_t<IsArrayEmpty<TMF>,
TMajorClass,
PolicySelRes<TMF>>;
};
template <typename TMajorClass, typename TPolicyContainer>
using PolicySelect = typename Selector_<TMajorClass, TPolicyContainer>::type;
只是返回false的模板:
template <typename T>
constexpr bool DependencyFalse = false;
主体函数:
template <typename... TPolicies>
struct Accumulator
{
using TPoliCont = PolicyContainer<TPolicies...>;
using TPolicyRes = PolicySelect<AccPolicy, TPoliCont>;
using ValueType = typename TPolicyRes::Value;
static constexpr bool is_ave = TPolicyRes::IsAve;
using AccuType = typename TPolicyRes::Accu;
public:
template <typename TIn>
static auto Eval(const TIn &in)
{
if constexpr (std::is_same<AccuType, AccPolicy::AccuTypeCate::Add>::value)
{
ValueType count = 0;
ValueType res = 0;
for (const auto &x : in)
{
res += x;
count += 1;
}
if constexpr (is_ave)
return res / count;
else
return res;
}
else if constexpr (std::is_same<AccuType, AccPolicy::AccuTypeCate::Mul>::value)
{
ValueType res = 1;
ValueType count = 0;
for (const auto &x : in)
{
res *= x;
count += 1;
}
if constexpr (is_ave)
return pow(res, 1.0 / count);
else
return res;
}
else
{
static_assert(DependencyFalse<AccuType>);
}
}
};
Policy定义(我不喜欢宏定义)
struct PMulAccu : virtual public AccPolicy
{
using MinorClass = AccPolicy::AccuTypeCate;
using Accu = AccPolicy::AccuTypeCate::Mul;
};
struct PAddAccu : virtual public AccPolicy
{
using MinorClass = AccPolicy::AccuTypeCate;
using Accu = AccPolicy::AccuTypeCate::Add;
};
struct PAve : virtual public AccPolicy
{
using MinorClass = AccPolicy::IsAveValueCate;
static constexpr bool IsAve = true;
};
struct PNoAve : virtual public AccPolicy
{
using MinorClass = AccPolicy::IsAveValueCate;
static constexpr bool IsAve = false;
};
template <typename T>
struct PValueTypeIs : virtual public AccPolicy
{
using MinorClass = AccPolicy::ValueTypeCate;
using Value = T;
};

浙公网安备 33010602011771号