pezy / CppPrimer

:books: Solutions for C++ Primer 5th exercises.
http://dwz.cn/cp5answer
Creative Commons Zero v1.0 Universal
3.29k stars 1.44k forks source link

ex16_29 include error file,It compile failed #184

Closed Layty closed 4 years ago

Layty commented 4 years ago

ex16_29 include error file 16.24.blob, it use the std::shared_ptr Then I fix it,It will show

In file included from e:\Reading\C++\C+++Primer\CppPrimer-master\CppPrimer-master\ch16\ex16_29_blob_test.cpp:1:0:
e:\Reading\C++\C+++Primer\CppPrimer-master\CppPrimer-master\ch16\ex16_29_blob.h: In instantiation of 'ConstBlobPtr< <template-parameter-1-1> >::ConstBlobPtr(const Blob<T>&, size_t) [with T = std::__cxx11::basic_string<char>; size_t = long long unsigned int]':
e:\Reading\C++\C+++Primer\CppPrimer-master\CppPrimer-master\ch16\ex16_29_blob_test.cpp:19:39:   required from here
e:\Reading\C++\C+++Primer\CppPrimer-master\CppPrimer-master\ch16\ex16_29_blob.h:347:74: error: no matching function for call to 'std::weak_ptr<std::vector<std::__cxx11::basic_string<char>, std::allocator<std::__cxx11::basic_string<char> > > >::weak_ptr(const SharedPtr<std::vector<std::__cxx11::basic_string<char>, std::allocator<std::__cxx11::basic_string<char> > > >&)'
     ConstBlobPtr(const Blob<T>& s, size_t sz = 0) : wptr(s.data), curr(sz) {}
                                                                          ^
In file included from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/memory:82:0,
                 from e:\Reading\C++\C+++Primer\CppPrimer-master\CppPrimer-master\ch16\ex16_29_blob.h:10,
                 from e:\Reading\C++\C+++Primer\CppPrimer-master\CppPrimer-master\ch16\ex16_29_blob_test.cpp:1:
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/bits/shared_ptr.h:492:2: note: candidate: template<class _Tp1, class> std::weak_ptr<_Tp>::weak_ptr(std::weak_ptr<_Tp1>&&)
Layty commented 4 years ago

对于我们自己的SharedPtr,无法对weak_ptr赋值,这里我们能怎么做


weak_ptr& operator=( const weak_ptr& r ) noexcept; | (1) | (C++11 起)
-- | -- | --
template< class Y > weak_ptr& operator=( const weak_ptr<Y>& r ) noexcept; | (2) | (C++11 起)
template< class Y > weak_ptr& operator=( const shared_ptr<Y>& r ) noexcept; | (3) | (C++11 起)
weak_ptr& operator=( weak_ptr&& r ) noexcept; | (4) | (C++14 起)
template< class Y > weak_ptr& operator=( weak_ptr<Y>&& r ) noexcept;
Layty commented 4 years ago

I remove the iterator


#include <vector>
#include <memory>
#include <string>
#include <list>
#include <iostream>
#include <initializer_list>
#include <exception>
#include <algorithm>

template <class T>
class SharedPtr
{
    using DelFuncPtr = void (*)(T *);

private:
    T *ptr_ = nullptr;
    size_t *count_ptr_ = nullptr;
    DelFuncPtr del_ = nullptr;

public:
    SharedPtr(T *ptr = nullptr, DelFuncPtr del = nullptr) : ptr_(ptr), del_(del), count_ptr_(new size_t(ptr_ != nullptr)) {}
    SharedPtr(const SharedPtr &s) : ptr_(s.ptr_), del_(s.del_), count_ptr_(s.count_ptr_)
    {
        ++*s.count_ptr_;
    }
    SharedPtr &operator=(SharedPtr s) //这里使用值传递,会先复制一份
    {
        //交换自己和临时的,临时的在退出的时候会自动调用析构释放
        swap(s);
        return *this;
    }

    void reset(T *ptr = nullptr, DelFuncPtr d = nullptr)
    {
        auto news = SharedPtr(ptr, d);
        swap(news);
    }

    void swap(SharedPtr &r) noexcept
    {
        using std::swap;
        swap(ptr_, r.ptr_);
        swap(count_ptr_, r.count_ptr_);
        swap(del_, r.del_);
    }
    ~SharedPtr()
    {
        if (ptr_ == nullptr)
            return;
        if (0 == --*count_ptr_)
        {
            del_ == nullptr ? delete (ptr_) : del_(ptr_);
            delete count_ptr_;
        }
        ptr_ = nullptr;
        count_ptr_ = nullptr;
    }

    T *get() const noexcept
    {
        return ptr_;
    }

    size_t use_count() const noexcept
    {
        return *count_ptr_;
    }

    T &operator*() const noexcept
    {
        return *ptr_;
    }
    T *operator->() const noexcept
    {
        return ptr_;
    }
    //检查 *this 是否存储非空指针,即是否有 get() != nullptr
    explicit operator bool() const noexcept
    {
        return get() != nullptr;
    }
};

template <typename T>
class Blob;

template <typename T>
bool operator==(const Blob<T> &a, const Blob<T> &b);
template <typename T>
bool operator!=(const Blob<T> &a, const Blob<T> &b);
template <typename T>
bool operator<(const Blob<T> &a, const Blob<T> &b);
template <typename T>
bool operator>(const Blob<T> &a, const Blob<T> &b);
template <typename T>
bool operator<=(const Blob<T> &a, const Blob<T> &b);
template <typename T>
bool operator>=(const Blob<T> &a, const Blob<T> &b);

template <typename T>
class Blob
{

    friend bool operator==<T>(const Blob<T> &a, const Blob<T> &b);
    friend bool operator!=<T>(const Blob<T> &a, const Blob<T> &b);
    // clang-format off
    friend bool operator< <T>(const Blob<T> &a, const Blob<T> &b);
    friend bool operator> <T>(const Blob<T> &a, const Blob<T> &b);
    // clang-format on
    friend bool operator<=<T>(const Blob<T> &a, const Blob<T> &b);
    friend bool operator>=<T>(const Blob<T> &a, const Blob<T> &b);

    // 以下两个应该是为了外部方便获取类型
    typedef T value_type;
    typedef typename std::vector<T>::size_type size_type;

private:
    SharedPtr<std::vector<T>> data;
    void check(size_type i, const std::string &msg) const;

public:
    Blob() : data(new std::vector<T>()) {}
    // 16.24
    template <typename type_it>
    Blob(type_it a, type_it b) : data(new std::vector<T>(a, b)) {}

    Blob(const Blob<T> &s) : data(new std::vector<T>(*s.data)) {}
    Blob(Blob<T> &&a) noexcept : data(std::move(a.data)) {}

    Blob &operator=(const Blob<T> &s);
    Blob &operator=(Blob<T> &&) noexcept;

    Blob(std::initializer_list<T> il) : data(new std::vector<T>(il)) {}
    size_type size() const { return data->size(); }
    bool empty() const { return data->empty(); }

    void push_back(T &val) { data->push_back(val); };
    void push_back(const T &val) { data->push_back(std::move(val)); }
    void pop_back();

    T &back();
    const T &back() const;
    T &front();
    const T &front() const;

    T &operator[](size_type i);
    const T &operator[](size_type i) const;

    void print(std::ostream &o);
};

template <typename T>
Blob<T> &Blob<T>::operator=(const Blob<T> &s)
{
    data = new std::vector<T>(*s.data);
    return *this;
}

template <typename T>
Blob<T> &Blob<T>::operator=(Blob<T> &&s) noexcept
{
    if (this != s)
    {
        data = std::move(s.data);
        s.data = nullptr;
    }
    return *this;
}

template <typename T>
void Blob<T>::print(std::ostream &o)
{
    for (auto ch : (*data))
        o << ch << ",";
    o << std::endl;
}

template <typename T>
void Blob<T>::check(size_type i, const std::string &msg) const
{
    if (i >= size())
    {
        throw std::out_of_range(msg);
    }
}

template <typename T>
void Blob<T>::pop_back()
{
    check(0, "empty to pop_back");
    data->pop_back();
}

template <typename T>
T &Blob<T>::back()
{
    check(0, "Get empty Back()");
    return data->back();
}
template <typename T>
const T &Blob<T>::back() const
{
    check(0, "Get empty Back()");
    return data->back();
}

template <typename T>
T &Blob<T>::front()
{
    check(0, "Get empty front()");
    return data->front();
}
template <typename T>
const T &Blob<T>::front() const
{
    check(0, "Get empty front()");
    return data->front();
}

template <typename T>
T &Blob<T>::operator[](size_type i)
{
    check(i, "Get [" + std::to_string(i) + "]");
    return data->at(i);
}

template <typename T>
const T &Blob<T>::operator[](size_type i) const
{
    check(i, "Get [" + std::to_string(i) + "]");
    return data->at(i);
}

//****************************************************************************
template <typename T>
bool operator==(const Blob<T> &a, const Blob<T> &b)
{
    return (*a.data == *b.data);
}
template <typename T>
bool operator!=(const Blob<T> &a, const Blob<T> &b)
{
    return !(a == b);
}

template <typename T>
bool operator<(const Blob<T> &a, const Blob<T> &b)
{
    return std::lexicographical_compare(a.data->begin(), a.data->end(), b.data->begin(), b.data->end());
}

template <typename T>
bool operator>(const Blob<T> &a, const Blob<T> &b)
{
    return (b < a);
}
template <typename T>
bool operator<=(const Blob<T> &a, const Blob<T> &b)
{
    return !(b > a);
}
template <typename T>
bool operator>=(const Blob<T> &a, const Blob<T> &b)
{
    return !(a < b);
}

int main(int argc, const char **argv)
{
    Blob<std::string> blob_s({"1", "2"});
    blob_s.print(std::cout);
    while (1)
        ;
    return 0;
}