通过提供类Tuple的API,可以为任意类型实现结构化绑定支持,就像标准库中std::pair,std::tuple和std::array所做的那样。
下面的例子演示了如何使类型Customer支持结构化绑定:
lang/customer1.hpp
- #include // for std::move()
复制代码- Customer (std::string f, std::string l, long v)
复制代码- : first{std::move(f)}, last{std::move(l)}, val{v} {
复制代码- std::string getFirst() const {
复制代码- std::string getLast() const {
复制代码 可以实现类Tuple API如下:
lang/structbind1.hpp
- #include // for tuple-like API
复制代码- // 为类型Customer实现类Tuple API以支持结构化绑定:
复制代码- static constexpr int value = 3; // 有 3 个属性(成员变量)
复制代码- struct std::tuple_element {
复制代码- using type = long; // 最后一个属性类型是long
复制代码- struct std::tuple_element {
复制代码- using type = std::string; // 其他属性类型都是strings
复制代码- template auto get(const Customer& c);
复制代码- template auto get(const Customer& c) { return c.getFirst(); }
复制代码- template auto get(const Customer& c) { return c.getLast(); }
复制代码- template auto get(const Customer& c) { return c.getValue(); }
复制代码 这里我们为Customer的3个属性(成员变量)定义类Tuple API,因此可以很容易地把3个getter映射到Customer上(任何其他用户定义的映射都是可以的):
- 第一个名字的类型是std::string
- 最后一个名字的类型是std::string
- 其他值类型是long
属性个数通过为Customer类型特化std::tuple_size来定义:
- static constexpr int value = 3; // 有3 个属性
复制代码 通过特化std::tuple_element来定义属性类型:
- struct std::tuple_element {
复制代码- using type = long; // 最后一个属性是 long
复制代码- struct std::tuple_element {
复制代码- using type = std::string; // 其他属性是string
复制代码 第3个属性类型是long,由全特化index 2指定。其他属性通过偏特化(优先级比全特化低)指定类型为std::string。这里指定的类型,跟结构化绑定decltype得到的类型一致。
最后,通过在同一名字空间内为类型Customer重载get()函数,就可以定义对应的getter:
- template auto get(const Customer& c);
复制代码- template auto get(const Customer& c) { return c.getFirst(); }
复制代码- template auto get(const Customer& c) { return c.getLast(); }
复制代码- template auto get(const Customer& c) { return c.getValue(); }
复制代码 在这个示例中,我们用到了主函数模板声明和全特化。
要注意的是,所有函数模板的全特化必须使用相同的函数签名(包括确切的返回值类型)。理由是我们只提供了特定的“实现”,没有新的声明。下面的代码就编译不过:
- template auto get(const Customer& c);
复制代码- template std::string get(const Customer& c) { return c.getFirst(); }
复制代码- template std::string get(const Customer& c) { return c.getLast(); }
复制代码- template long get(const Customer& c) { return c.getValue(); }
复制代码 使用编译期if特性,可以将get()实现合并到一个函数中:
- template auto get(const Customer& c) {
复制代码- else if constexpr (I == 1) {
复制代码 有了这个API,我们就可以像下面这样使用Customer的结构化绑定:
lang/structbind1.cpp
- #include "structbind1.hpp"
复制代码- Customer c{"Tim", "Starr", 42};
复制代码 [code] std::cout |
|