草庐IT

c++ - 结构化绑定(bind)宽度

coder 2024-02-02 原文

是否可以使用结构化绑定(bind)语法来确定我应该在方括号中指定多少个变量名,以匹配普通右侧 struct 的数据成员数量?

我想制作通用库的一部分,它使用结构化绑定(bind)将任意类分解为其组成部分。目前还没有结构化绑定(bind)的可变版本(而且,我认为,不能用于当前提议的语法),但我的第一个想法是对某些函数 decompose() 进行一组重载,它将 struct 参数分解为其组成部分。 decompose() 应该由参数(即 struct)数据成员的数量重载。目前 constexpr if 语法也可用于分派(dispatch)它。但是,为了上述目的,我如何模拟类似于 sizeof... 运算符的东西呢?我不能在 SFINAE 构造中的某处使用 auto [a, b, c] 语法,因为它是分解声明 并且据我所知,任何声明都不能在 中使用decltype,我也不能在 lambda 函数体中出于我的目的使用它,因为 lambda 函数也不能在模板参数中使用。

我当然想要内置运算符(语法如 sizeof[] S/sizeof[](S) for class S) , 但像下面这样的东西也是可以接受的:

template< typename type, typename = void >
struct sizeof_struct
{

};

template< typename type >
struct sizeof_struct< type, std::void_t< decltype([] { auto && [p1] = std::declval< type >(); void(p1); }) > >
    : std::integral_constant< std::size_t, 1 >
{

};

template< typename type >
struct sizeof_struct< type, std::void_t< decltype([] { auto && [p1, p2] = std::declval< type >(); void(p1); void(p2);  }) > >
    : std::integral_constant< std::size_t, 2 >
{

};

... etc up to some reasonable arity

也许 constexpr lambda 将允许我们将它们用于模板的参数中。你怎么看?

即将到来的概念有可能吗?

最佳答案

struct two_elements {
  int x;
  double y;
};

struct five_elements {
  std::string one;
  std::unique_ptr<int> two;
  int * three;
  char four;
  std::array<two_elements, 10> five;
};

struct anything {
  template<class T> operator T()const;
};

namespace details {
  template<class T, class Is, class=void>
  struct can_construct_with_N:std::false_type {};

  template<class T, std::size_t...Is>
  struct can_construct_with_N<T, std::index_sequence<Is...>, std::void_t< decltype(T{(void(Is),anything{})...}) >>:
  std::true_type
  {};
}
template<class T, std::size_t N>
using can_construct_with_N=details::can_construct_with_N<T, std::make_index_sequence<N>>;

namespace details {
  template<std::size_t Min, std::size_t Range, template<std::size_t N>class target>
  struct maximize:
    std::conditional_t<
      maximize<Min, Range/2, target>{} == (Min+Range/2)-1,
      maximize<Min+Range/2, (Range+1)/2, target>,
      maximize<Min, Range/2, target>
    >
  {};
  template<std::size_t Min, template<std::size_t N>class target>
  struct maximize<Min, 1, target>:
    std::conditional_t<
      target<Min>{},
      std::integral_constant<std::size_t,Min>,
      std::integral_constant<std::size_t,Min-1>
    >
  {};
  template<std::size_t Min, template<std::size_t N>class target>
  struct maximize<Min, 0, target>:
    std::integral_constant<std::size_t,Min-1>
  {};

  template<class T>
  struct construct_searcher {
    template<std::size_t N>
    using result = ::can_construct_with_N<T, N>;
  };
}

template<class T, std::size_t Cap=20>
using construct_airity = details::maximize< 0, Cap, details::construct_searcher<T>::template result >;

这对 T 的最长构造空气度进行二分搜索从 0 到 20。20 是一个常量,您可以根据需要增加它,但会增加编译时和内存开销。

Live example .

如果你的结构中的数据不能从它自己类型的右值构造,它不会在 C++14 中工作,但我相信 guanteed elision 发生在 C++17 here (!)

将其转换为结构化绑定(bind)需要的不仅仅是一堆手动代码。但是一旦你知道了,你应该能够提出诸如“这个 struct 的第三种类型是什么”之类的问题。

如果 struct可以在没有 tuple_size 的情况下分解为结构化绑定(bind)事情正在做,它的通风性决定了它需要多少变量。

不幸的是std::tuple_size即使在 C++17 中也不是 SFINAE 友好的。但是,使用 tuple_size 的类型部分还需要启用 ADL std::get .

使用 failure_tag get<std::size_t>(Ts const&...) 创建命名空间那using std::get .使用它来检测它们是否已覆盖 get<0>在类型 ( !std::is_same< get_type<T,0>, failure_tag >{} ) 上,如果是这样,请往下 tuple_element确定通风的路径。将生成的元素填充到 std::tuple 中的 decltype(get<Is>(x))并归还。

如果失败,使用上面的 construct_airity ,并用它来弄清楚如何在类型上使用结构化绑定(bind)。然后我可能会将其发送到 std::tie , 为了统一。

我们现在有tuple_it它接受任何类似结构化绑定(bind)的东西并将其转换为引用或值的元组。 现在两条路径都收敛了,您的通用代码更容易了!

关于c++ - 结构化绑定(bind)宽度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39768517/

有关c++ - 结构化绑定(bind)宽度的更多相关文章

  1. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

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

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

  3. ruby - ruby 中的 TOPLEVEL_BINDING 是什么? - 2

    它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput

  4. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

  5. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  6. ruby-on-rails - 创建 ruby​​ 数据库时惰性符号绑定(bind)失败 - 2

    我正在尝试在Rails上安装ruby​​,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf

  7. ruby-on-rails - 一般建议和推荐的文件夹结构 - Sinatra - 2

    您将如何构建一个简单的Sinatra应用程序?我正在制作,我希望该应用具有以下功能:“应用程序”更像是一个包含所有信息的管理仪表板。然后另一个应用程序将通过REST访问信息。我还没有创建仪表板,只是从数据库中获取东西session和身份验证(尚未实现)您可以上传图片,其他应用可以显示这些图片我已经使用RSpec创建了一个测试文件通过Prawn生成报告目前的设置是这样的:app.rbtest_app.rb因为我实际上只有应用程序和测试文件。到目前为止,我已经将Datamapper用于ORM,将SQLite用于数据库。这是我的第一个Ruby/Sinatra项目,所以欢迎任何和所有建议-我应

  8. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  9. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

  10. ruby - 如何在 ruby​​ 中复制目录结构,不包括某些文件扩展名 - 2

    我想编写一个ruby​​脚本来递归复制目录结构,但排除某些文件类型。因此,给定以下目录结构:folder1folder2file1.txtfile2.txtfile3.csfile4.htmlfolder2folder3file4.dll我想复制这个结构,但不包含.txt和.cs文件。因此,生成的目录结构应如下所示:folder1folder2file4.htmlfolder2folder3file4.dll 最佳答案 您可以使用查找模块。这是一个代码片段:require"find"ignored_extensions=[".cs"

随机推荐