草庐IT

c++ - 将集合论应用于 C++11 可变参数模板

coder 2024-02-08 原文

假设我有两个可变参数模板; typename...T,typename...U,我该如何找到它们;

  1. 串联
  2. 最大公共(public)子序列
  3. 最大公共(public)子序列的逆

据我了解,连接很简单; (t..., u...),但是如何找到两者的最大公共(public)子序列呢? - 这有可能吗?

最佳答案

这是一个计算对元组类型对的集合操作的解决方案。我假设元组可以用来保存变量参数包,所以一旦你有了 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 - Concatenation

这个很简单:

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 - Longest common subsequence

这个稍微更复杂:

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

这是一个反转类型序列的特征(返回一个带有反转类型列表的元组):

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

这不是要求的,而是作为奖励提供的:

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!"
        );

关于c++ - 将集合论应用于 C++11 可变参数模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15274816/

有关c++ - 将集合论应用于 C++11 可变参数模板的更多相关文章

  1. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  2. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  3. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  4. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  5. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  6. ruby - 通过 erb 模板输出 ruby​​ 数组 - 2

    我正在使用puppet为ruby​​程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby​​不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这

  7. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

  8. ruby-on-rails - Rails 应用程序中的 Rails : How are you using application_controller. rb 是新手吗? - 2

    刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr

  9. ruby - 如何在 Ruby 中拆分参数字符串 Bash 样式? - 2

    我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"

  10. ruby - 检查方法参数的类型 - 2

    我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)

随机推荐