使用boost::hana中的second函数

424 篇文章 ¥29.90 ¥99.00
本文介绍了C++编程中,如何利用boost::hana库的second函数来方便地获取元组的第二个元素,从而简化代码,提高编程效率。

使用boost::hana中的second函数

在C++编程中,操作元组是一个很常见的任务。然而,标准库并不提供一些便利的函数来操作元组,这就使得代码看起来比较冗长。为了解决这个问题,boost::hana库提供了一组工具函数来方便操作元组。

其中,second函数就是一个非常有用的工具函数,它可以获取元组中第二个元素的值。下面是一个简单的示例程序:

#include <boost/hana.hpp>
#include <iostream>
#include <string>

namespace hana = boost::hana;

int main() {
    // 定义一个包含两个元素的元组
    auto my_tuple = hana::make_tuple(1, std::string("hello"));

    // 使用second函数获取元组的第二个元素
    auto second_element = hana::second(my_tuple);

    // 输出结果
    std::cout << "Second element: " << second_element << std::endl;

    return 0;
}

在上面的程序中,我们首先使用hana::make_tuple函数创建了一个包含两个元素的元组,并将其赋值给变量my_tuple。接着,我们使用hana::second函数获取了元组的第二个元素,也就是"hello"字符串。最

Macros We love and hate C++ because the language allows us to do almost anything. Macros are the most flexible tool in the arsenal of C++’s foot-guns. There’s a lot you can do with macros that you could instead do with templates, which grants you type safety, better error handling, and often better optimizations than macros. However, reflection can’t be achieved with templates alone and must leverage macros (until C++17, as we’ll see in the next section). The Boost C++ libraries offer a few utility libraries for template metaprogramming, including MPL, Fusion, and Hana. Fusion and Hana both offer macros that can adapt a user-defined POD-type into an introspectible structure which tuple-like access. I’ll focus on Hana because I’m more familiar with the library and it’s a newer library. However, the macro offered by Fusion has the same interface. The Hana documentation gives a full overview of these macros. You can either define an introspectible struct with BOOST_HANA_DEFINE_STRUCT: struct Person { BOOST_HANA_DEFINE_STRUCT(Person, (std::string, name), (std::string, last_name), (int, age) ); }; Or, if you’d like to introspect a type defined by another library, you can use BOOST_HANA_ADAPT_STRUCT: BOOST_HANA_ADAPT_STRUCT(Person, name, last_name, age); After doing this, you can access the struct in a generic fashion. For example, you can iterate over the fields of the struct using hana::for_each: Person jackie{"Jackie", "Kay", 24}; hana::for_each(jackie, [](auto pair) { std::cout << hana::to<char const*>(hana::first(pair)) << ": " << hana::second(pair) << std::endl; }); // name: Jackie // last_name: Kay // age: 24 The basic idea behind the magic is that the macro generates generic set and get functions for each member. It “stringizes” the field name given to the macro so it can be used as a constexpr string key, and uses the identifier name and type to get the member pointer for each field. Then it adapts the struct to a tuple of compile-time string key, member pointer accessor pairs. Though that sounds fairly straightforward, the code is quite formidable and verbose. That’s because there’s a separate macro case for adapting a struct of specific sizes. For example, all structs with 1 member map to a particular macro, all structs with 2 members map to the next macro, etc. The macro is actually generated from a less than 200-line Ruby template. You might not know Ruby, but you can get a taste of the pattern by looking at the template, which can be expanded for a maximum of n=62 (line breaks are my own): #define BOOST_HANA_DEFINE_STRUCT(...) \ BOOST_HANA_DEFINE_STRUCT_IMPL(BOOST_HANA_PP_NARG(__VA_ARGS__), __VA_ARGS__) #define BOOST_HANA_DEFINE_STRUCT_IMPL(N, ...) \ BOOST_HANA_PP_CONCAT(BOOST_HANA_DEFINE_STRUCT_IMPL_, N)(__VA_ARGS__) <% (0..MAX_NUMBER_OF_MEMBERS).each do |n| %> #define BOOST_HANA_DEFINE_STRUCT_IMPL_<%= n+1 %>(TYPE <%= (1..n).map { |i| ", m#{i}" }.join %>) \ <%= (1..n).map { |i| "BOOST_HANA_PP_DROP_BACK m#{i} BOOST_HANA_PP_BACK m#{i};" }.join(' ') %> \ \ struct hana_accessors_impl { \ static constexpr auto apply() { \ struct member_names { \ static constexpr auto get() { \ return ::boost::hana::make_tuple( \ <%= (1..n).map { |i| \ "BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m#{i})" }.join(', ') %> \ ); \ } \ }; \ return ::boost::hana::make_tuple( \ <%= (1..n).map { |i| "::boost::hana::make_pair( \ ::boost::hana::struct_detail::prepare_member_name<#{i-1}, member_names>(), \ ::boost::hana::struct_detail::member_ptr< \ decltype(&TYPE::BOOST_HANA_PP_BACK m#{i}), \ &TYPE::BOOST_HANA_PP_BACK m#{i}>{})" }.join(', ') %> \ ); \ } \ } \ Why did the authors of these libraries write these macros in the first place? Bragging rights, of course! Actually, tuple-like access for structs is incredibly useful for generic programming. It allows you to perform operations on every member of a type, or a subset of members conforming to a particular concept, without having to know the specific names of each member. Again, this is a feature that you can’t get with inheritance, templates, and concepts alone. The major disadvantage of these macros is that to reflect on a type you either need to define it withDEFINE_STRUCT, or to refer to it and all of its introspectible members in the correct order withADAPT_STRUCT. Though the solution requires less logical and code redundancy than code generation techniques, this last bit of hand-hacking wouldn’t be required if we had language-level reflection.翻译
06-04
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值