板凳——————————————————c++(84)

//2020年07月07日 22时26分32秒
#include <cstddef>
#include <vector>
#include <list>
#include <string>
#include <functional>
#include <iostream>
#include <iterator>
#include <stdexcept>
#include <algorithm>
#include <utility>

class MoveableClass  //p492
{
public:
    MoveableClass() {
        std::cout << "Default constructor" << std::endl;
    }
    MoveableClass(const MoveableClass& /* src */) {
        std::cout << "Copy constructor" << std::endl;
    }
    MoveableClass(MoveableClass&& /* src */) noexcept {
        std::cout << "Move constructor" << std::endl;
    }
    MoveableClass& operator=(const MoveableClass& /* rhs */) {
        std::cout << "Copy assignment operator" << std::endl;
        return *this;
    }
    MoveableClass& operator=(MoveableClass&& /* rhs */) noexcept {
        std::cout << "Move assignment operator" << std::endl;
        return *this;
    }
};

template <typename InputIterator, typename OutputIterator, typename Predicate>
OutputIterator find_all(InputIterator first, InputIterator last,
    OutputIterator dest, Predicate pred)
{
    while (first != last) {
        if (pred(*first)) {
            *dest = first;
            ++dest;
        }
        ++first;
    }
    return dest;
}

template <typename IteratorType>
void iteratorTraitsTest(IteratorType it)
{
    typename std::iterator_traits<IteratorType>::value_type temp;
    temp = *it;
    //auto temp = *it;
    std::cout << temp << std::endl;
}

namespace ProCpp {

    // A default hash object
    template <typename T>
    class hash
    {
    public:
        size_t operator()(const T& key) const;
    };

    // A hash specialization for strings
    template <>
    class hash<std::string>
    {
    public:
        size_t operator()(const std::string& key) const;
    };

    template <typename Key, typename T,     //p740
        typename KeyEqual = std::equal_to<>,
        typename Hash = hash<Key>>
class hash_map
{
public:
    using key_type = Key;
    using mapped_type = T;
    using value_type = std::pair<const Key, T>;

    // Virtual destructor
    virtual ~hash_map() = default;

    // Throws invalid_argument if the number of buckets is illegal.
    explicit hash_map(const KeyEqual& equal = KeyEqual(),
                      size_t numBuckets = 101, const Hash& hash = Hash());

    // Copy constructor
    hash_map(const hash_map<Key, T, KeyEqual, Hash>& src) = default;
    // Move constructor
    hash_map(hash_map<Key, T, KeyEqual, Hash>&& src) noexcept = default;

    // Copy assignment operator
    hash_map<Key, T, KeyEqual, Hash>& operator=(const hash_map<Key, T, KeyEqual, Hash>& rhs);
    // Move assignment operator
        hash_map<Key, T, KeyEqual, Hash>& operator=(hash_map<Key, T, KeyEqual, Hash>&& rhs) noexcept;

    // Inserts the key/value pair x.
    void insert(const value_type& x);

    // Removes the element with key k, if it exists.
    void erase(const key_type& k);

    // Removes all elements.
    void clear() noexcept;

    // Find returns a pointer to the element with key k.
    // Returns nullptr if no element with that key exists.
    value_type* find(const key_type& k);
    const value_type* find(const key_type& k) const;

    // operator[] finds the element with key k, or inserts an
    // element with that key if none exists yet. Returns a reference to
    // the value corresponding to that key.
    T& operator[] (const key_type& k);

    // Swaps two hash_maps.
    void swap(hash_map<Key, T, KeyEqual, Hash>& other) noexcept;

private:
    using ListType = std::list<value_type>;

    // Returns a pair containing an iterator to the found element with a given key,
    // and the index of that element's bucket.
    std::pair<typename ListType::iterator, size_t> findElement(const key_type& k);

    std::vector<ListType> mBuckets;
    size_t mSize = 0;
    KeyEqual mEqual;
    Hash mHash;
    };
}
//professional c++ 4th edition p742
    // Calculate a hash by treating the key as a sequence
    // of bytes and summing the ASCII values of the bytes.
    template <typename T>
    size_t ProCpp::hash<T>::operator()(const T& key) const
    {
        const size_t bytes = sizeof(key);
        size_t sum = 0;
        for (size_t i = 0; i < bytes; ++i) {
            unsigned char b = *(reinterpret_cast<const unsigned char*>(&key) + i);
            sum += b;
        }
        return sum;
    }

    // Calculate a hash by summing the ASCII values of all characters.
    size_t ProCpp::hash<std::string>::operator()(const std::string& key) const
    {
        size_t sum = 0;
        for (auto c : key) {
            sum += static_cast<unsigned char>(c);
        }
        return sum;
    }

    template <typename Key, typename T, typename KeyEqual, typename Hash>
    void swap(ProCpp::hash_map<Key, T, KeyEqual, Hash>& first, ProCpp::hash_map<Key, T, KeyEqual, Hash>& second) noexcept
    {
        first.swap(second);
    }

    // Construct mBuckets with the correct number of buckets.
    template <typename Key, typename T, typename KeyEqual, typename Hash>
    ProCpp::hash_map<Key, T, KeyEqual, Hash>::hash_map(const KeyEqual& equal, size_t numBuckets, const Hash& hash)
        : mBuckets(numBuckets), mEqual(equal), mHash(hash)
    {
        if (numBuckets == 0) {
            throw std::invalid_argument("Number of buckets must be positive");
        }
    }

    template <typename Key, typename T, typename KeyEqual, typename Hash>
    ProCpp::hash_map<Key, T, KeyEqual, Hash>& ProCpp::hash_map<Key, T, KeyEqual, Hash>::operator=(const hash_map<Key, T, KeyEqual, Hash>& rhs)
    {
        // check for self-assignment
        if (this == &rhs) {
            return *this;
        }

        // Copy-and-swap idiom
        auto copy = rhs;  // Do all the work in a temporary instance
        swap(copy);       // Commit the work with only non-throwing operations
        return *this;
    }

    template <typename Key, typename T, typename KeyEqual, typename Hash>
    ProCpp::hash_map<Key, T, KeyEqual, Hash>& ProCpp::hash_map<Key, T, KeyEqual, Hash>::operator=(hash_map<Key, T, KeyEqual, Hash>&& rhs) noexcept
    {
        swap(rhs);
        return *this;
    }

    template <typename Key, typename T, typename KeyEqual, typename Hash>
    std::pair<typename ProCpp::hash_map<Key, T, KeyEqual, Hash>::ListType::iterator, size_t>
        ProCpp::hash_map<Key, T, KeyEqual, Hash>::findElement(const key_type& k)
    {
        // Hash the key to get the bucket.
        size_t bucket = mHash(k) % mBuckets.size();

        // Search for the key in the bucket.
        auto iter = find_if(begin(mBuckets[bucket]), end(mBuckets[bucket]),
            [this, &k](const auto& element) { return mEqual(element.first, k); });

        // Return a pair of the iterator and the bucket index.
        return std::make_pair(iter, bucket);
    }

    template <typename Key, typename T, typename KeyEqual, typename Hash>
    typename ProCpp::hash_map<Key, T, KeyEqual, Hash>::value_type* ProCpp::hash_map<Key, T, KeyEqual, Hash>::find(const key_type& k)
    {
        // Use the findElement() helper, and C++17 structured bindings.
        auto[it, bucket] = findElement(k);
        if (it == end(mBuckets[bucket])) {
            // Element not found -- return nullptr.
            return nullptr;
        }
        // Element found -- return a pointer to it.
        return &(*it);
    }

    template <typename Key, typename T, typename KeyEqual, typename Hash>
    const typename ProCpp::hash_map<Key, T, KeyEqual, Hash>::value_type* ProCpp::hash_map<Key, T, KeyEqual, Hash>::find(const key_type& k) const
    {
        return const_cast<hash_map<Key, T, KeyEqual, Hash>*>(this)->find(k);
    }

    template <typename Key, typename T, typename KeyEqual, typename Hash>
    T& ProCpp::hash_map<Key, T, KeyEqual, Hash>::operator[] (const key_type& k)
    {
        // Try to find the element. If it doesn't exist, add a new element.
        auto[it, bucket] = findElement(k);
        if (it == end(mBuckets[bucket])) {
            mSize++;
            mBuckets[bucket].push_back(std::make_pair(k, T()));
            return mBuckets[bucket].back().second;
        } else {
            return it->second;
        }
    }

    template <typename Key, typename T, typename KeyEqual, typename Hash>
    void ProCpp::hash_map<Key, T, KeyEqual, Hash>::insert(const value_type& x)
    {
        // Try to find the element.
        auto[it, bucket] = findElement(x.first);

        if (it != end(mBuckets[bucket])) {
            // The element already exists.
            return;
        } else {
            // We didn't find the element, so insert a new one.
            mSize++;
            mBuckets[bucket].push_back(x);
        }
    }

    template <typename Key, typename T, typename KeyEqual, typename Hash>
    void ProCpp::hash_map<Key, T, KeyEqual, Hash>::erase(const key_type& k)
    {
        // First, try to find the element.
        auto[it, bucket] = findElement(k);

        if (it != end(mBuckets[bucket])) {
            // The element exists -- erase it.
            mBuckets[bucket].erase(it);
            mSize--;
        }
    }

    template <typename Key, typename T, typename KeyEqual, typename Hash>
    void ProCpp::hash_map<Key, T, KeyEqual, Hash>::clear() noexcept
    {
        // Call clear on each bucket.
        for (auto& bucket : mBuckets) {
            bucket.clear();
        }
        mSize = 0;
    }

    template <typename Key, typename T, typename KeyEqual, typename Hash>
    void ProCpp::hash_map<Key, T, KeyEqual, Hash>::swap(hash_map<Key, T, KeyEqual, Hash>& other) noexcept
    {
        using std::swap;

        swap(mBuckets, other.mBuckets);
        swap(mSize, other.mSize);
        swap(mEqual, other.mEqual);
        swap(mHash, other.mHash);
    }

 

int main()
{
    std::vector<MoveableClass> vecSource;
    MoveableClass mc;
    vecSource.push_back(mc);
    vecSource.push_back(mc);
    std::cout << "----" << std::endl;
//Without using move_iterators, this code triggers the copy constructor two times, once for every element
//in vecSource p763
    // Copy the elements from vecSource to vecOne
    std::vector<MoveableClass> vecOne(cbegin(vecSource), cend(vecSource));
    std::cout << "----" << std::endl;
    
    // Move the elements from vecSource to vecTwo
    std::vector<MoveableClass> vecTwo(std::make_move_iterator(begin(vecSource)),
                      std::make_move_iterator(end(vecSource)));
    // Using C++17's template argument deduction for constructors.
    //vector<MoveableClass> vecTwo(move_iterator(begin(vecSource)),
    //                             move_iterator(end(vecSource)));
    std::cout << "----" << std::endl;

    
    std::vector<int> vec{ 3, 4, 5, 4, 5, 6, 5, 8 };
    std::vector<std::vector<int>::iterator> matches;

    find_all(begin(vec), end(vec), back_inserter(matches), [](int i){ return i == 5; });

    std::cout << "Found " << matches.size() << " matching elements: " << std::endl;

    for (const auto& it : matches) {
        std::cout << *it << " at position " << (it - cbegin(vec)) << std::endl;;
    }
    std::cout << std::endl;
    
    std::vector<int> v{ 5 };
    iteratorTraitsTest(cbegin(v));
    
    
    ProCpp::hash_map<int, int> myHash;
    myHash.insert(std::make_pair(4, 40));
    myHash.insert(std::make_pair(6, 60));

    // x will have type hash_map<int, int>::value_type*
    auto x = myHash.find(4);
    if (x != nullptr) {
        std::cout << "4 maps to " << x->second << std::endl;
    } else {
        std::cout << "cannot find 4 in map" << std::endl;
    }

    myHash.erase(4);

    auto x2 = myHash.find(4);
    if (x2 != nullptr) {
        std::cout << "4 maps to " << x2->second << std::endl;
    } else {
        std::cout << "cannot find 4 in map" << std::endl;
    }

    myHash[4] = 35;
    myHash[4] = 60;

    auto x3 = myHash.find(4);
    if (x3 != nullptr) {
        std::cout << "4 maps to " << x3->second << std::endl;
    } else {
        std::cout << "cannot find 4 in map" << std::endl;
    }

    // Test std::swap().
    ProCpp::hash_map<int, int> other(std::equal_to<>(), 11);
    swap(other, myHash);

    // Test copy construction and copy assignment.
    ProCpp::hash_map<int, int> myHash2(other);
    ProCpp::hash_map<int, int> myHash3;
    myHash3 = myHash2;

    // Test move construction and move assignment.
    ProCpp::hash_map<int, int> myHash4(std::move(myHash3));
    ProCpp::hash_map<int, int> myHash5;
    myHash5 = std::move(myHash4);

    return 0;
}
/*
wannian07@wannian07-PC:~$ g++ -std=c++17 -o c13 c13.cpp -pthread
wannian07@wannian07-PC:~$ ./c13
Default constructor
Copy constructor
Copy constructor
Move constructor
----
Copy constructor
Copy constructor
----
Move constructor
Move constructor
----

Found 3 matching elements:
5 at position 2
5 at position 4
5 at position 6

5

4 maps to 40
cannot find 4 in map
4 maps to 60

*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值