集合论在c++ 11可变模板中的应用
Applying set-theory to C++11 variadic templates
假设我有两个可变的模板;typename... T, typename... U
,我该如何找到他们的;
- 连接
- 最大公共子序列
- 最大公共子序列的逆
所以从我的理解,连接是简单的;(t..., u...)
,但是找到这两个的最大公共子序列呢?-这可能吗?
这里是对元组类型对计算集合操作的解决方案。我假设元组可以用来保存变量参数包,这样一旦您有了Ts...
和Us...
,您就可以:
typename tuple_intersect<std::tuple<Ts...>, std::tuple<Us...>>::type
这给了你一个元组,其中Vs...
是Ts...
和Us...
的交集。如果您需要再次提取Vs...
作为参数包,只需提供元组作为接受tuple<Ts...>
的函数的输入:
template<typename... Vs>
void func(std::tuple<Vs...>)
{
// Here, you have Vs... (= Us... & Ts...) as an argument pack
}
:
下面是一些简单的元函数,它们是下面所有主要元函数所共有的:
template<typename T, typename... Ts>
struct is_member_of_type_seq { static const bool value = false; };
template<typename T, typename U, typename... Ts>
struct is_member_of_type_seq<T, U, Ts...>
{
static const bool value = std::conditional<
std::is_same<T, U>::value,
std::true_type,
is_member_of_type_seq<T, Ts...>
>::type::value;
};
template<typename, typename>
struct append_to_type_seq { };
template<typename T, typename... Ts>
struct append_to_type_seq<T, std::tuple<Ts...>>
{
using type = std::tuple<Ts..., T>;
};
template<typename, typename>
struct prepend_to_type_seq { };
template<typename T, typename... Ts>
struct prepend_to_type_seq<T, std::tuple<Ts...>>
{
using type = std::tuple<T, Ts...>;
};
1 - 连接
这个很简单:
template<typename, typename>
struct concat_type_seq { };
template<typename... Ts, typename... Us>
struct concat_type_seq<std::tuple<Ts...>, std::tuple<Us...>>
{
using type = std::tuple<Ts..., Us...>;
};
和一些测试:
static_assert(
std::is_same<
concat_type_seq<
std::tuple<char, int, bool>,
std::tuple<double, double, int>
>::type,
std::tuple<char, int, bool, double, double, int>
>::value,
"Error"
);
2 - 最长公共子序列
这个稍微复杂一点:
namespace detail
{
// Meta-function that returns, given two sequences S1 and S2, the longest
// subsequence of S1 in S2 that starts with the first element of S1 and
// begins at the first element of S2 (in other words, it returns the
// subsequence S2[0]..S2[N] such that S1[i] = S2[i] for each 0 <= i <= N.
template<typename, typename>
struct match_seq_in_seq_from_start
{
using type = std::tuple<>;
};
template<typename T, typename U, typename... Ts, typename... Us>
struct match_seq_in_seq_from_start<std::tuple<T, Ts...>, std::tuple<U, Us...>>
{
using type = typename std::conditional<
std::is_same<T, U>::value,
typename prepend_to_type_seq<
T,
typename match_seq_in_seq_from_start<
std::tuple<Ts...>,
std::tuple<Us...>
>::type
>::type,
std::tuple<>
>::type;
};
// Some testing...
static_assert(
std::is_same<
match_seq_in_seq_from_start<
std::tuple<int, double, char>,
std::tuple<int, double, long>
// ^^^^^^^^^^^
>::type,
std::tuple<int, double>
>::value,
"Error!"
);
// Meta-function that returns the same as the meta-function above,
// but starting from the first element of S2 which is identical to
// the first element of S1.
template<typename, typename>
struct match_first_seq_in_seq
{
using type = std::tuple<>;
};
template<typename T, typename U, typename... Ts, typename... Us>
struct match_first_seq_in_seq<std::tuple<T, Ts...>, std::tuple<U, Us...>>
{
using type = typename std::conditional<
std::is_same<T, U>::value,
typename match_seq_in_seq_from_start<
std::tuple<T, Ts...>,
std::tuple<U, Us...>
>::type,
typename match_first_seq_in_seq<
std::tuple<T, Ts...>,
std::tuple<Us...>
>::type
>::type;
};
// Some testing...
static_assert(
std::is_same<
match_first_seq_in_seq<
std::tuple<int, double, char>,
std::tuple<bool, char, int, double, long, int, double, char>
// ^^^^^^^^^^^
>::type,
std::tuple<int, double>
>::value,
"Error!"
);
// Meta-function that returns, given two sequences S1 and S2, the longest
// subsequence of S1 in S2 that starts with the first element of S1.
template<typename T, typename U>
struct match_seq_in_seq
{
using type = std::tuple<>;
};
template<typename U, typename... Ts, typename... Us>
struct match_seq_in_seq<std::tuple<Ts...>, std::tuple<U, Us...>>
{
using type1 = typename match_first_seq_in_seq<
std::tuple<Ts...>,
std::tuple<U, Us...>
>::type;
using type2 = typename match_seq_in_seq<
std::tuple<Ts...>,
std::tuple<Us...>
>::type;
using type = typename std::conditional<
(std::tuple_size<type1>::value > std::tuple_size<type2>::value),
type1,
type2
>::type;
};
// Some testing...
static_assert(
std::is_same<
match_seq_in_seq<
std::tuple<int, double, char>,
std::tuple<char, int, double, long, int, double, char>
// ^^^^^^^^^^^^^^^^^
>::type,
std::tuple<int, double, char>
>::value,
"Error!"
);
}
// Meta-function that returns, given two sequences S1 and S2, the longest
// subsequence of S1 in S2 (longest common subsequence).
template<typename T, typename U>
struct max_common_subseq
{
using type = std::tuple<>;
};
template<typename T, typename... Ts, typename... Us>
struct max_common_subseq<std::tuple<T, Ts...>, std::tuple<Us...>>
{
using type1 = typename detail::match_seq_in_seq<
std::tuple<T, Ts...>,
std::tuple<Us...>
>::type;
using type2 = typename max_common_subseq<
std::tuple<Ts...>,
std::tuple<Us...>
>::type;
using type = typename std::conditional<
(std::tuple_size<type1>::value > std::tuple_size<type2>::value),
type1,
type2
>::type;
};
和一些测试:
// Some testing...
static_assert(
std::is_same<
max_common_subseq<
std::tuple<int, double, char>,
std::tuple<char, int, char, double, char, long, int, bool, double>
>::type,
std::tuple<double, char>
>::value,
"Error!"
);
// Some more testing...
static_assert(
std::is_same<
max_common_subseq<
std::tuple<int, double, char, long, long, bool>,
// ^^^^^^^^^^^^^^^^
std::tuple<char, long, long, double, double, char>
// ^^^^^^^^^^^^^^^^
>::type,
std::tuple<char, long, long>
>::value,
"Error!"
);
3 - 反转
这是一个反转类型序列的trait(返回一个带有反转类型列表的元组):
template<typename... Ts>
struct revert_type_seq
{
using type = std::tuple<>;
};
template<typename T, typename... Ts>
struct revert_type_seq<T, Ts...>
{
using type = typename append_to_type_seq<
T,
typename revert_type_seq<Ts...>::type
>::type;
};
和一些测试:
// Some testing...
static_assert(
std::is_same<
revert_type_seq<char, int, bool>::type,
std::tuple<bool, int, char>
>::value,
"Error"
);
4 - 路口
这个不是要求的,但作为奖励提供:
template<typename, typename>
struct intersect_type_seq
{
using type = std::tuple<>;
};
template<typename T, typename... Ts, typename... Us>
struct intersect_type_seq<std::tuple<T, Ts...>, std::tuple<Us...>>
{
using type = typename std::conditional<
!is_member_of_type_seq<T, Us...>::value,
typename intersect_type_seq<
std::tuple<Ts...>,
std::tuple<Us...>>
::type,
typename prepend_to_type_seq<
T,
typename intersect_type_seq<
std::tuple<Ts...>,
std::tuple<Us...>
>::type
>::type
>::type;
};
和一些测试:
// Some testing...
static_assert(
std::is_same<
intersect_type_seq<
std::tuple<char, int, bool, double>,
std::tuple<bool, long, double, float>
>::type,
std::tuple<bool, double>
>::value,
"Error!"
);
相关文章:
- 试图在visual studio上用C++创建一个桌面应用程序
- FFmpeg:制作一个应用程序比直接使用ffmepg更好吗
- c++r值引用应用于函数指针
- 在C应用程序中运行C++(带有STL)函数
- 使用VerQueryValue检索应用程序的文件描述
- Qt C++静态thread_local QNetworkAccessManager是线程应用程序的好选择吗
- 使用调试/崩溃报告将应用程序部署到客户端
- C++控制台应用程序阻止退出
- 码头化的C++应用程序是否向后兼容早期的内核版本
- 将应用程序从32位移植到64位时出现问题
- 有没有任务栏API可以立即应用注册表更改
- 如何改变c++应用程序的视觉效果
- WM_CTLCOLORSTATIC从未在WIN32应用程序中触发
- PC中的程序和PHONE中的本机描述应用程序之间的数据连接
- 应用程序崩溃并显示"symbol _ZdlPvm, version Qt_5 not defined in file libQt5Core.so.5 with link time reference"
- 示例外壳应用程序显示的 V8 "segmentation fault (core dumped)"错误
- phytec phyBOARD iMX-6在从闪存而不是SD卡运行qt5 opengles应用程序时表现不佳(FPS减半
- TMap::Emplace() 在应用现有密钥时会覆盖吗?
- 为什么导入Mixed native/CLR lib.dll的本机C++应用程序没有在Mixed lib.dll中的外部变
- 如何从Windows应用程序输出到标准?