草庐IT

c++17 通过生成预先声明的类型列表的笛卡尔积来制作 std::variant

coder 2024-02-03 原文

假设我有一个包含三个模板类型参数的类。

template<typename Transformer, typename Criteria, typename Strategy>
struct ConfiguredPipeline {};

并且有以下类稍后在实例化 ConfiguredPipeline 时使用:

template<typename...>
struct CriteriaList
{
};
using SupportedCriteria = CriteriaList<ChiSquared, Cosine>;

template<typename...>
struct StrategiesList
{
};
using SupportedStrategies = StrategiesList<Voting>;

template<typename...>
struct TransformerList
{
};
using SupportedTransformer = TransformerList<AAGrouper11, AAGrouper15>;

我如何能够生成一个 std::variant 等价于:

using PipelineVariant = std::variant< 
ConfiguredPipeline< ChiSquared , Voting , AAGrouper11 > ,
ConfiguredPipeline< ChiSquared , Voting , AAGrouper15 > ,
ConfiguredPipeline< Cosine , Voting , AAGrouper11 > ,
ConfiguredPipeline< Cosine , Voting , AAGrouper15 >>;

通过简单地调用一个函数,例如:

using PipelineVariant = makeVariant< ConfiguredPipeline , SupportedCriteria , SupportedStrategies, SupportedTransformaers >;

最佳答案

我想 decltype()std::declval()std::tuple_cat() 可以帮到你很多。

给定以下声明的几个重载模板(注意:已声明,未定义,遵循 std::declval() 示例)函数来生成类型的笛卡尔积并折叠(感谢std::tuple_cat()) 在单个 std::tuple

template <template <typename...> class C, typename ... Ts>
constexpr std::tuple<C<Ts...>> tupleExpand (std::tuple<Ts...> const &);

template <template <typename...> class C, typename ... Ts,
          template <typename...> class C0, typename ... Ls,
          typename ... Cs>
constexpr auto tupleExpand (std::tuple<Ts...> const &, C0<Ls...> const &,
                            Cs const & ... cs)
   -> decltype(std::tuple_cat(
         tupleExpand<C>(std::declval<std::tuple<Ts..., Ls>>(), cs...)...));

和以下简单模板函数(同样:仅声明)将 std::tuple 类型转换为相应 std::variant 列表中的类型列表类型

template <typename ... Ts>
constexpr std::variant<Ts...> tupleToVariant (std::tuple<Ts...> const &);

你可以写一个MakeVariant类如下

template <template <typename...> class C, typename ... Ts>
struct MakeVariant
 {
   using type = decltype(tupleToVariant(std::declval<
                   decltype(tupleExpand<C>(std::declval<std::tuple<>>(),
                                           std::declval<Ts>()...))>()));
 };

还有一个简单的 using 助手

template <template <typename...> class C, typename ... Ts>
using MakeVariantType = typename MakeVariant<C, Ts...>::type;

你可以定义你的 PipelineVariant 类型如下

using PipelineVariant = MakeVariantType<ConfiguredPipeline,
                                        SupportedCriteria,
                                        SupportedStrategies,
                                        SupportedTransformers>;

下面是一个完整的编译示例

#include <tuple>
#include <variant>

template <typename, typename, typename>
struct ConfiguredPipeline
 { };

struct ChiSquared {};
struct Cosine     {};

template <typename...>
struct CriteriaList
 { };

using SupportedCriteria = CriteriaList<ChiSquared, Cosine>;

struct Voting {};

template <typename...>
struct StrategiesList
 { };

using SupportedStrategies = StrategiesList<Voting>;

struct AAGrouper11 { };
struct AAGrouper15 { };

template <typename...>
struct TransformerList
 { };

using SupportedTransformers = TransformerList<AAGrouper11, AAGrouper15>;

template <template <typename...> class C, typename ... Ts>
constexpr std::tuple<C<Ts...>> tupleExpand (std::tuple<Ts...> const &);

template <template <typename...> class C, typename ... Ts,
          template <typename...> class C0, typename ... Ls,
          typename ... Cs>
constexpr auto tupleExpand (std::tuple<Ts...> const &, C0<Ls...> const &,
                            Cs const & ... cs)
   -> decltype(std::tuple_cat(
         tupleExpand<C>(std::declval<std::tuple<Ts..., Ls>>(), cs...)...));

template <typename ... Ts>
constexpr std::variant<Ts...> tupleToVariant (std::tuple<Ts...> const &);

template <template <typename...> class C, typename ... Ts>
struct MakeVariant
 {
   using type = decltype(tupleToVariant(std::declval<
                           decltype(tupleExpand<C>(std::declval<std::tuple<>>(),
                                                   std::declval<Ts>()...))>()));
 };

template <template <typename...> class C, typename ... Ts>
using MakeVariantType = typename MakeVariant<C, Ts...>::type;

using PipelineVariant = MakeVariantType<ConfiguredPipeline,
                                        SupportedCriteria,
                                        SupportedStrategies,
                                        SupportedTransformers>;

int main () 
 {
   static_assert(std::is_same<PipelineVariant, 
                              std::variant<ConfiguredPipeline<ChiSquared, Voting, AAGrouper11>,
                                           ConfiguredPipeline<ChiSquared, Voting, AAGrouper15>,
                                           ConfiguredPipeline<Cosine, Voting, AAGrouper11>,
                                           ConfiguredPipeline<Cosine, Voting, AAGrouper15>>>::value);
 }

关于c++17 通过生成预先声明的类型列表的笛卡尔积来制作 std::variant,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51696418/

有关c++17 通过生成预先声明的类型列表的笛卡尔积来制作 std::variant的更多相关文章

  1. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  2. ruby - 通过 rvm 升级 ruby​​gems 的问题 - 2

    尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub

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

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

  4. ruby - 在 jRuby 中使用 'fork' 生成进程的替代方案? - 2

    在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',

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

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

  6. ruby - 如何使用 Ruby aws/s3 Gem 生成安全 URL 以从 s3 下载文件 - 2

    我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A

  7. ruby - RVM 使用列表[0] - 2

    是否有类似“RVMuse1”或“RVMuselist[0]”之类的内容而不是键入整个版本号。在任何时候,我们都会看到一个可能包含5个或更多ruby的列表,我们可以轻松地键入一个数字而不是X.X.X。这也有助于rvmgemset。 最佳答案 这在RVM2.0中是可能的=>https://docs.google.com/document/d/1xW9GeEpLOWPcddDg_hOPvK4oeLxJmU3Q5FiCNT7nTAc/edit?usp=sharing-知道链接的任何人都可以发表评论

  8. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

  9. ruby-on-rails - active_admin 目录中的常量警告重新声明 - 2

    我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA

  10. ruby - 通过 RVM (OSX Mountain Lion) 安装 Ruby 2.0.0-p247 时遇到问题 - 2

    我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search

随机推荐