C++の最上位constと最上位constおよびアナログスマートポインタ.

7967 ワード

 #include <iostream>
#include <memory>
/*                  const     :
              Node<int> = const Node<int>& , Node<int> = Node<int>&.
    : Node(const Node<int>&)     operator=(const Node<int>&).
          Node(Node<int>&)   operator=(Node<int>&) . 
*/ 
 
template<typename T>
class Node{
 private:
  T* key_ptr;
  mutable unsigned int counter_; //    .    mutable,    Node const         . 
  
  public:
   template<typename Ty>
   explicit Node(const Ty& key_); //explicit:      . 
   
   Node();
   
   Node(const Node<T>& other_node_);
   
   template<typename Ty>
   Node(Node<Ty>&& other_node_);
   
   Node<T>& operator=(const Node<T>& other_node_);
   
   template<typename Ty>
   Node<Ty>& operator=(Node<Ty>&& other_node);
   
   T* get_key_ptr()const noexcept; //     const. 
   
   operator T*()const noexcept;
   
   ~Node();
};
template<typename T>
Node<T>::Node()
        :key_ptr(nullptr),
         counter_(1)
{
 //default constructor.
}
template<typename T>
template<typename Ty>
Node<T>::Node(const Ty& key_)
        :key_ptr(new Ty(key_)),
         counter_(1)
{
 //constructor.
}
template<typename T>
template<typename Ty>
Node<T>::Node(Node<Ty>&& other_node_)
{
 if(this->counter_ == 1){
  delete key_ptr;
  this->key_ptr = nullptr;
 }
 
 this->key_ptr = other_node_.key_ptr;
 this->counter_ = other_node_.counter_;
 
 other_node_.counter = 0; 
}
template<typename T>
Node<T>::Node(const Node<T>& other_node_)
{
 if(--(this->counter_) == 0){
  delete key_ptr;
  this->key_ptr = nullptr;
 }
 
 other_node_.counter_ += 1;
 this->counter_ = other_node_.counter_;
}
template<typename T>
template<typename Ty>
Node<Ty>& Node<T>::operator=(Node<Ty>&& other_node_)
{
 if(--(this->counter_) == 0){
  delete key_ptr;
  this->key_ptr = nullptr;
 }
 
 this->key_ptr = other_node_.key_ptr;
 this->counter_ = other_node_.counter_;
 other_node_.counter_ = 0;
 other_node_.key_ptr = nullptr;
 
 return *this;
}
template<typename T>
Node<T>& Node<T>::operator=(const Node<T>& other_node_)
{
 if(--(this->counter_) == 0){
  delete key_ptr;
  this->key_ptr = nullptr;
 }
 
 other_node_.counter_ += 1;
 this->key_ptr = other_node_.key_ptr;
 this->counter_ = other_node_.counter_;
 
 return *this;
}
template<typename T>
T* Node<T>::get_key_ptr()const noexcept
{
 return this->key_ptr;
}
template<typename T>
Node<T>::operator T*()const noexcept 
{
 return this->key_ptr;
}
template<typename T>
Node<T>::~Node()
{
 if(this->key_ptr = nullptr){
  return;
 }
 
 --(this->counter_);
 if(this->counter_ == 0){
  delete key_ptr;
  this->counter_ = 0;
  this->key_ptr = nullptr;
 }
}
template<typename T>
void function(const Node<T>& node) //      const   :  node key_ptr    T* const. 
{
 T*  ptr = node.get_key_ptr(); //  get_key_ptr     . 
 std::cout<<"The contents of key_ptr: "<<*ptr;
 
 //delete ptr; //     delete   node  key_ptr           . 
}
template<typename T>
class Edge{
 private:
  int number_;
  
  public:
   template<typename Ty>
   Edge(const Ty& number);
   
   Edge();
   
   const int& get_mem()const;
   
   ~Edge()=default;
};
template<typename T>
template<typename Ty>
Edge<T>::Edge(const Ty& number)
        :number_(number)
{
 //
}
template<typename T>
const int& Edge<T>::get_mem()const //       const,     (const int&)  const.             const. 
{
 return this->number_;
}
int main()
{
 Node<int> first_(10);
 Node<int> second_;
 
 second_ = first_; //first  key_ptr          delete  . 
 
 //function(first_); //  . 
 
 const Node<int> third_(30); //third_  key_ptr   :T* const. 
 
 int* ptr = third_.get_key_ptr();
 std::cout<<*ptr<<std::endl;
 
 int* const first_ptr = new int(2);
 int* second_ptr = first_ptr; //ok.  int* = int* const. 
 second_ptr = nullptr;
 delete first_ptr;
 
 const int* third_ptr = new int(3);
 //int* forth_ptr = third_ptr; //  : const int* = int*.  
 delete third_ptr;
 
 Node<int> forth_(40);
 if(forth_ != nullptr){ //             operator T*(). 
  std::cout<<"successfully!"<<std::endl;
 }
 
 Edge<int> edge_one(1);
 int one = edge_one.get_mem(); //  :  int& = const int&. 
 
 const int& two = 0;     //const int& = int
 const int& three = one; //const int& = int
 
 int four = three;      //int = const int&
 
 //       :Node<int> = const Node<int>&
 //                Node<int> = Node<int>&
 
 Node<int> fifth_(50); 
 const Node<int>& sixth_ (Node<int>(60)); //        . 
 Node<int>& seventh_ = fifth_; 
 
 Node<int> eighth_ = sixth_; 
 Node<int> ninth_ = seventh_; 
 
 return 0;
}

2016/3/24:
より良いソリューション
 #include <iostream>
#include <memory>
template<typename T>
class Node{
 private:
  std::shared_ptr<T> key_ptr_;
  
  public:
   Node()=default;
   
   template<typename Ty>
   explicit Node(const Ty& key_);
   
   Node(const Node<T>& other_node_);
   
   template<typename Ty>
   Node(Node<Ty>&& other_node_);
   
   Node<T>& operator=(const Node<T>& other_node_);
   
   template<typename Ty>
   Node<Ty>& operator=(Node<Ty>&& other_node_);
   
   void print()const;
   
   ~Node();
};
template<typename T>
template<typename Ty>
Node<T>::Node(const Ty& key_)
        :key_ptr_(std::make_shared<Ty>(key_))
{
 //
}
template<typename T>
Node<T>::Node(const Node<T>& other_node_)
        :key_ptr_(other_node_.key_ptr_)
{
 //
}
template<typename T>
template<typename Ty>
Node<T>::Node(Node<Ty>&& other_node_)
        :key_ptr_(other_node_.key_ptr_)
{
 (other_node_.key_ptr_).reset(nullptr); //          key_ptr_          +1,   reset(nullptr)        -1. 
}
template<typename T>
Node<T>& Node<T>::operator=(const Node<T>& other_node_)
{
 this->key_ptr_ = other_node_.key_ptr_;
 
 return *this;
}
template<typename T>
template<typename Ty>
Node<Ty>& Node<T>::operator=(Node<Ty>&& other_node_)
{
 this->key_ptr_ = other_node_.key_ptr_;
 
 (other_node_.key_ptr).reset();
 
 return *this;
}
template<typename T>
Node<T>::~Node()
{
 if(this->key_ptr_ == nullptr){
  return;
 }
 
 std::cout<<"counter: "<<(this->key_ptr_).use_count();
 (this->key_ptr_).reset();
}
template<typename T>
void Node<T>::print()const
{
 std::cout<<*(this->key_ptr_)<<std::endl;
}
template<typename T>
void function(Node<T> node) //copy node.
{
 node.print();
}
int main()
{
 Node<int> first_(10);
 
 Node<int>& second_ = first_;
 
 function(second_);
 
 return 0;
}