使用可变参数模板实现类型列表替换操作
implementing typelist replace operation using variadic templates
我正在尝试为类型列表的可变参数模板版本实现 ReplaceAll 元函数(受 Modern C++ Design 启发),到目前为止,我可以使用以下代码实现所需的结果:
template <typename... Elements> struct Typelist {};
//
// helper metafunction to set "Head" of typelist
//
template <typename TList, typename T> struct PushFrontT;
template <typename... Elements, typename T>
struct PushFrontT<Typelist<Elements...>, T> {
using Result = Typelist<T, Elements...>;
};
//
// metafunction to replace all occurences of "T" with "U"
//
template <typename TList, typename T, typename U> struct ReplaceAll;
template <typename T, typename U>
struct ReplaceAll<Typelist<>, T, U> {
using Result = Typelist<>;
};
template <typename... Tail, typename T, typename U>
struct ReplaceAll<Typelist<T, Tail...>, T, U> {
using Result = typename PushFrontT<
typename ReplaceAll<Typelist<Tail...>, T, U>::Result, U
>::Result;
};
template <typename Head, typename... Tail, typename T, typename U>
struct ReplaceAll<Typelist<Head, Tail...>, T, U> {
using Result = typename PushFrontT<
typename ReplaceAll<Typelist<Tail...>, T, U>::Result, Head
>::Result;
};
其中 returns 形式为 Typelist<T1, T2, T3>
的类型列表(有效地将所有出现的类型 T
替换为目标类型 U
)。
现在的问题是,当我尝试不使用辅助元函数 PushFrontT
时,将以 Typelist<T1, Typelist<T2, Typelist<T3, Typelist<>>>>
的形式创建嵌套类型列表结构,这是不正确的(尽管替换了所有实例T
与 U
).
错误版本代码如下:
template <typename T, typename U>
struct ReplaceAll<Typelist<>, T, U> {
using Result = Typelist<>;
};
template <typename... Tail, typename T, typename U>
struct ReplaceAll<Typelist<T, Tail...>, T, U> {
using Result = Typelist<U,
typename ReplaceAll<Typelist<Tail...>, T, U>::Result
>;
};
template <typename Head, typename... Tail, typename T, typename U>
struct ReplaceAll<Typelist<Head, Tail...>, T, U> {
using Result = Typelist<Head,
typename ReplaceAll<Typelist<Tail...>, T, U>::Result
>;
};
基于我对可变参数模板的有限了解,我认为额外的 Typelist
是 pack expansion 的副作用,但我不确定。
这是一个简单的测试程序来检查上述代码:
#include <type_traits>
int main () {
using tlist = Typelist<int, char, int, double>;
static_assert(
std::is_same<
typename ReplaceAll<tlist, int, long>::Result,
Typelist<long, char, long, double>>::value,
"Incorrect typelist!"
);
return(0);
}
简而言之,我的问题是如何在不使用外部辅助元函数(例如 PushFrontT
的情况下摆脱过多的嵌套 Typelist
?
您可以简化代码并使用
摆脱递归
template <typename TList, typename T, typename U> struct ReplaceAll;
template <typename ... Ts, typename T, typename U>
struct ReplaceAll<Typelist<Ts...>, T, U>
{
using Result = Typelist<std::conditional_t<std::is_same_v<Ts, T>, U, Ts>...>;
};
我正在尝试为类型列表的可变参数模板版本实现 ReplaceAll 元函数(受 Modern C++ Design 启发),到目前为止,我可以使用以下代码实现所需的结果:
template <typename... Elements> struct Typelist {};
//
// helper metafunction to set "Head" of typelist
//
template <typename TList, typename T> struct PushFrontT;
template <typename... Elements, typename T>
struct PushFrontT<Typelist<Elements...>, T> {
using Result = Typelist<T, Elements...>;
};
//
// metafunction to replace all occurences of "T" with "U"
//
template <typename TList, typename T, typename U> struct ReplaceAll;
template <typename T, typename U>
struct ReplaceAll<Typelist<>, T, U> {
using Result = Typelist<>;
};
template <typename... Tail, typename T, typename U>
struct ReplaceAll<Typelist<T, Tail...>, T, U> {
using Result = typename PushFrontT<
typename ReplaceAll<Typelist<Tail...>, T, U>::Result, U
>::Result;
};
template <typename Head, typename... Tail, typename T, typename U>
struct ReplaceAll<Typelist<Head, Tail...>, T, U> {
using Result = typename PushFrontT<
typename ReplaceAll<Typelist<Tail...>, T, U>::Result, Head
>::Result;
};
其中 returns 形式为 Typelist<T1, T2, T3>
的类型列表(有效地将所有出现的类型 T
替换为目标类型 U
)。
现在的问题是,当我尝试不使用辅助元函数 PushFrontT
时,将以 Typelist<T1, Typelist<T2, Typelist<T3, Typelist<>>>>
的形式创建嵌套类型列表结构,这是不正确的(尽管替换了所有实例T
与 U
).
错误版本代码如下:
template <typename T, typename U>
struct ReplaceAll<Typelist<>, T, U> {
using Result = Typelist<>;
};
template <typename... Tail, typename T, typename U>
struct ReplaceAll<Typelist<T, Tail...>, T, U> {
using Result = Typelist<U,
typename ReplaceAll<Typelist<Tail...>, T, U>::Result
>;
};
template <typename Head, typename... Tail, typename T, typename U>
struct ReplaceAll<Typelist<Head, Tail...>, T, U> {
using Result = Typelist<Head,
typename ReplaceAll<Typelist<Tail...>, T, U>::Result
>;
};
基于我对可变参数模板的有限了解,我认为额外的 Typelist
是 pack expansion 的副作用,但我不确定。
这是一个简单的测试程序来检查上述代码:
#include <type_traits>
int main () {
using tlist = Typelist<int, char, int, double>;
static_assert(
std::is_same<
typename ReplaceAll<tlist, int, long>::Result,
Typelist<long, char, long, double>>::value,
"Incorrect typelist!"
);
return(0);
}
简而言之,我的问题是如何在不使用外部辅助元函数(例如 PushFrontT
的情况下摆脱过多的嵌套 Typelist
?
您可以简化代码并使用
摆脱递归template <typename TList, typename T, typename U> struct ReplaceAll;
template <typename ... Ts, typename T, typename U>
struct ReplaceAll<Typelist<Ts...>, T, U>
{
using Result = Typelist<std::conditional_t<std::is_same_v<Ts, T>, U, Ts>...>;
};