EOS区块链C++语言开发Multi-Index容器

我们将讨论的最后一个重要主题是Multi-Index。标准库附带了许多容器,如 vector S(动态数组), list S(双链表), set S或 map S。虽然所有这些都用于存储和访问元素的相同目的,但它们中的每一个都以不同方式实现,导致基本操作的不同运行时间。例如, set 以排序的方式维护其元素,而 list 不产生随机访问但允许你可以在恒定时间内在任何地方插入元素而无需重新分配。它们都提供了访问元素的单一特定方式,但有时我们希望有多个接口来访问相同的数据。

我们来看一下 CryptoCurrency 类:

#include <iostream>
#include <set>
#include <string>
#include <algorithm>

using namespace std;

class CryptoCurrency {
    public:
    string name;
    uint64_t market_cap;
    double priceInUSD;
    CryptoCurrency(const string &name, uint64_t market_cap, double priceInUSD) : name(name), market_cap(market_cap), priceInUSD(priceInUSD) {}
    
    // define comparison < operator to compare cryptos by market_cap 
    bool operator<(const CryptoCurrency& c) const {
        return market_cap < c.market_cap;
    }
};

int main()
{
    // store some crypto currencies in a set
    set<CryptoCurrency> cryptos;
    cryptos.insert(CryptoCurrency("EOS", 1000, 1.0));
    cryptos.insert(CryptoCurrency("Bitcoin", 2000, 10.0));
    cryptos.insert(CryptoCurrency("Ethereum", 500, 2.0));
    
    // sets order their elements, in our case according to market_cap
    // iterating the currencies in ascending order
    for_each(cryptos.begin(), cryptos.end(), [](const CryptoCurrency& c) {
        cout << c.name << " " << c.market_cap << "\n";
    });
}

在我们的例子中, market_cap 是一个很好的方法来保持单个索引排序的加密货币。但是,如果你需要按字母顺序排列的货币列表,会发生什么?

一种方法是这一次保持一组指向由 name 字段排序的 set 元素的指针。但是,有一种更简单的方法:我们需要的是一种为同一数据元素定义多个索引的方法。

这正是boost库中 multi_index_containers 的概念。

Boost库是一个在实践中高度使用的外部库,因为它解决了C++标准库中没有的各种常见任务,附带了很好的文档和教程,并且是开源和同行评审的。(你也可以在写智能合约时使用它!)

“对于大多数程序员来说,显而易见的解决方案是使用一个独立于所需服务的优雅高效平台的库。例如BOOST ......” -  Bjarne Stroustrup

让我们来看看如何让我们的类使用 multi_index_container

#include <iostream>
#include <set>
#include <string>
#include <algorithm>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/member.hpp>

using namespace std;
using namespace boost; // for multi_index_container
// for indexed_by, ordered_unique, member, identity
using namespace boost::multi_index;

class CryptoCurrency
{
  public:
    string name;
    uint64_t market_cap;
    double priceInUSD;
    CryptoCurrency(const string &name, uint64_t market_cap, double priceInUSD) : name(name), market_cap(market_cap), priceInUSD(priceInUSD) {}

    // define comparison < operator to compare cryptos by market_cap
    bool operator<(const CryptoCurrency &c) const
    {
        return market_cap < c.market_cap;
    }
};

// typedef is a way to alias types
// multi_index_container<...> will be aliased as crypto_set
typedef multi_index_container
<
    CryptoCurrency,
    indexed_by
    <
        // sort by CryptoCurrency::operator<
        ordered_unique<identity<CryptoCurrency>>,
        // sort by string's < on CryptoCurrency::name member
        ordered_unique<member<CryptoCurrency, std::string, &CryptoCurrency::name>>
    >
> crypto_set;

int main()
{
    // use the typedef'd multi_index_container
    crypto_set cryptos;
    cryptos.insert(CryptoCurrency("Eos", 1000, 1.0));
    cryptos.insert(CryptoCurrency("Bitcoin", 2000, 10.0));
    cryptos.insert(CryptoCurrency("Ethereum", 500, 2.0));

    // interface through the first index by market_cap
    // market_cap_index is now an iterator having .begin() and .end()
    // make sure to not forget the '&' after ::type or use auto
    const crypto_set::nth_index<0>::type &market_cap_index = cryptos.get<0>();
    for_each(market_cap_index.begin(), market_cap_index.end(), [](const CryptoCurrency &c) {
        cout << c.name << " " << c.market_cap << "\n";
    });

    // alternatively you can omit the .get<0>().begin() and call .begin() directly
    // not providing .get<index> always returns the first index
    // so we don't even need to change the old code for sorting by market_cap!
    for_each(cryptos.begin(), cryptos.end(), [](const CryptoCurrency &c) {
        cout << c.name << " " << c.market_cap << "\n";
    });

    // now interface through the _second_ index by name
    // const crypto_set::nth_index<1>::type& name_index = cryptos.get<1>();
    const auto &name_index = cryptos.get<1>();
    for_each(name_index.begin(), name_index.end(), [](const CryptoCurrency &c) {
        cout << c.name << " " << c.market_cap << "\n";
    });
}

索引类型多于 ordered_uniqueordered_non_unique (对于非唯一类成员)。虽然这两个提供类似于将 CryptoCurrency 存储为 std::set 的接口,但是有序的<>索引提供了像 std::list 这样的双向接口。当你想要保留插入元素的时间的原始顺序时,顺序索引很有用。如果你需要访问一个特定的位置,比如 std::vector ,那就有一个 random_access<> 索引。

当我们通过智能合约在EOS区块链中存储和检索数据表时,我们将重新访问multi_index_containers。可以想象,拥有多个接口来对数据库表中的元素进行排序和搜索非常有用。

如果你想了解更多关于它们的知识,boost.org有一个详尽的 教程

======================================================================

分享一些比特币、以太坊、EOS等区块链相关的交互式在线编程实战教程:

  • EOS入门教程,本课程帮助你快速入门EOS区块链去中心化应用的开发,内容涵盖EOS工具链、账户与钱包、发行代币、智能合约开发与部署、使用代码与智能合约交互等核心知识点,最后综合运用各知识点完成一个便签DApp的开发。
  • 深入浅出玩转EOS钱包开发 ,本课程以手机EOS钱包的完整开发过程为主线,深入学习EOS区块链应用开发,课程内容即涵盖账户、计算资源、智能合约、动作与交易等EOS区块链的核心概念,同时也讲解如何使用eosjs和eosjs-ecc开发包访问EOS区块链,以及如何在React前端应用中集成对EOS区块链的支持。课程内容深入浅出,非常适合前端工程师深入学习EOS区块链应用开发。
  • java比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Java代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Java工程师不可多得的比特币开发学习课程。
  • php比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Php代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Php工程师不可多得的比特币开发学习课程。
  • c#比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在C#代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是C#工程师不可多得的比特币开发学习课程。
  • java以太坊开发教程,主要是针对java和android程序员进行区块链以太坊开发的web3j详解。
  • python以太坊,主要是针对python工程师使用web3.py进行区块链以太坊开发的详解。
  • php以太坊,主要是介绍使用php进行智能合约开发交互,进行账号创建、交易、转账、代币开发以及过滤器和交易等内容。
  • 以太坊入门教程,主要介绍智能合约与dapp应用开发,适合入门。
  • 以太坊开发进阶教程,主要是介绍使用node.js、mongodb、区块链、ipfs实现去中心化电商DApp实战,适合进阶。
  • ERC721以太坊通证实战,课程以一个数字艺术品创作与分享DApp的实战开发为主线,深入讲解以太坊非同质化通证的概念、标准与开发方案。内容包含ERC-721标准的自主实现,讲解OpenZeppelin合约代码库二次开发,实战项目采用Truffle,IPFS,实现了通证以及去中心化的通证交易所。
  • C#以太坊,主要讲解如何使用C#开发基于.Net的以太坊应用,包括账户管理、状态与交易、智能合约开发与交互、过滤器和交易等。
  • Hyperledger Fabric 区块链开发详解 ,本课程面向初学者,内容即包含Hyperledger Fabric的身份证书与MSP服务、权限策略、通道配置与启动、链码通信接口等核心概念,也包含Fabric网络设计、nodejs链码与应用开发的操作实践,是Nodejs工程师学习Fabric区块链开发的最佳选择。
  • Hyperledger Fabric java 区块链开发详解 ,课程面向初学者,内容即包含Hyperledger Fabric的身份证书与MSP服务、权限策略、频道配置与启动、链码通信接口等核心概念,也包含Fabric网络设计、java链码与应用开发的操作实践,是java工程师学习Fabric区块链开发的最佳选择。
  • tendermint区块链开发详解 ,本课程适合希望使用tendermint进行区块链开发的工程师,课程内容即包括tendermint应用开发模型中的核心概念,例如ABCI接口、默克尔树、多版本状态库等,也包括代币发行等丰富的实操代码,是go语言工程师快速入门区块链开发的最佳选择。

汇智网原创翻译,转载请标明出处。这里是 EOS区块链C++语言开发Multi-Index容器

我来评几句
登录后评论

已发表评论数()

相关站点

热门文章