fork download
  1. //http://stackoverflow.com/questions/27433533/making-template-from-any-parameter-a-friend-to-template-with-one-parameter-c/27436693#27436693
  2.  
  3.  
  4. #include <type_traits>
  5. #include <memory>
  6. #include <iostream>
  7.  
  8. template<typename T, typename U>
  9. struct is_non_class_same : public std::integral_constant<bool, (!std::is_base_of<
  10. typename std::remove_pointer<T>::type,
  11. typename std::remove_pointer<U>::type>::value &&
  12. std::is_convertible<U, T>::value && sizeof(T) >= sizeof(U)) ||
  13. (std::is_class<T>::value && std::is_class<U>::value &&
  14. !std::is_pointer<T>::value && !std::is_pointer<U>::value &&
  15. std::is_same<T, U>::value)>
  16. {};
  17.  
  18. template<typename T, typename U>
  19. struct is_class_same : public std::integral_constant<bool, std::is_base_of<
  20. typename std::remove_pointer<T>::type,
  21. typename std::remove_pointer<U>::type>::value &&
  22. std::is_pointer<T>::value>
  23. {};
  24.  
  25.  
  26. class Node
  27. {
  28. protected:
  29. Node* previous;
  30. Node* next;
  31.  
  32. Node() : previous(nullptr), next(nullptr) {}
  33.  
  34. template<class T, class TD>
  35. friend class linked_ptr;
  36.  
  37. public:
  38. virtual ~Node() {}
  39.  
  40. };
  41.  
  42. template<typename T, typename TD = typename std::remove_pointer<T>::type>
  43. class linked_ptr : public Node
  44. {
  45. private:
  46. template<class, class> friend class linked_ptr; /** Access friend level **/
  47. T data;
  48.  
  49. public:
  50.  
  51. template<class U, typename TU = typename std::remove_pointer<U>::type, typename = typename std::enable_if<is_non_class_same<T, U>::value || is_class_same<T, U>::value, U>::type>
  52. linked_ptr(U data) : data(data) {}
  53. ~linked_ptr();
  54.  
  55. template<class U, typename TU = typename std::remove_pointer<U>::type, typename = typename std::enable_if<is_non_class_same<T, U>::value || is_class_same<T, U>::value, U>::type>
  56. void setData(U data)
  57. {
  58. this->data = data;
  59. }
  60.  
  61. template<class U, typename TU = typename std::remove_pointer<U>::type, typename = typename std::enable_if<is_non_class_same<T, U>::value || is_class_same<T, U>::value, U>::type>
  62. void append(U data);
  63. };
  64.  
  65. template<typename T, typename TD>
  66. linked_ptr<T, TD>::~linked_ptr()
  67. {
  68. TD(data);
  69. delete this->next;
  70. }
  71.  
  72. template<typename T, typename TD>
  73. template<typename U, typename TU, class>
  74. void linked_ptr<T, TD>::append(U data)
  75. {
  76. if (!this->next)
  77. {
  78. this->next = new linked_ptr<U, TU>(data);
  79. this->next->previous = this;
  80. return;
  81. }
  82.  
  83. Node* t = this->next;
  84. while(t->next != nullptr)
  85. {
  86. t = t->next;
  87. }
  88.  
  89. t->next = new linked_ptr<U, TU>(data);
  90. }
  91.  
  92.  
  93.  
  94.  
  95. class foo
  96. {
  97. public:
  98. virtual ~foo()
  99. {
  100. std::cout<<"destroyed foo\n";
  101. };
  102.  
  103. virtual void print()
  104. {
  105. std::cout<<"foo\n";
  106. }
  107. };
  108.  
  109. class bar : public foo
  110. {
  111. public:
  112. virtual ~bar()
  113. {
  114. std::cout<<"destroyed bar\n";
  115. }
  116.  
  117. virtual void print()
  118. {
  119. std::cout<<"bar\n";
  120. }
  121. };
  122.  
  123. int main()
  124. {
  125. linked_ptr<foo*> list(new foo());
  126. list.append(new bar());
  127. list.append(new bar());
  128. list.append(new bar());
  129. }
Success #stdin #stdout 0s 3432KB
stdin
Standard input is empty
stdout
destroyed bar
destroyed foo
destroyed bar
destroyed foo
destroyed bar
destroyed foo
destroyed foo