//http://stackoverflow.com/questions/27433533/making-template-from-any-parameter-a-friend-to-template-with-one-parameter-c/27436693#27436693
#include <type_traits>
#include <memory>
#include <iostream>
template<typename T, typename U>
struct is_non_class_same : public std::integral_constant<bool, (!std::is_base_of<
typename std::remove_pointer<T>::type,
typename std::remove_pointer<U>::type>::value &&
std::is_convertible<U, T>::value && sizeof(T) >= sizeof(U)) ||
(std::is_class<T>::value && std::is_class<U>::value &&
!std::is_pointer<T>::value && !std::is_pointer<U>::value &&
std::is_same<T, U>::value)>
{};
template<typename T, typename U>
struct is_class_same : public std::integral_constant<bool, std::is_base_of<
typename std::remove_pointer<T>::type,
typename std::remove_pointer<U>::type>::value &&
std::is_pointer<T>::value>
{};
class Node
{
protected:
Node* previous;
Node* next;
Node() : previous(nullptr), next(nullptr) {}
template<class T, class TD>
friend class linked_ptr;
public:
virtual ~Node() {}
};
template<typename T, typename TD = typename std::remove_pointer<T>::type>
class linked_ptr : public Node
{
private:
template<class, class> friend class linked_ptr; /** Access friend level **/
T data;
public:
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>
linked_ptr(U data) : data(data) {}
~linked_ptr();
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>
void setData(U data)
{
this->data = data;
}
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>
void append(U data);
};
template<typename T, typename TD>
linked_ptr<T, TD>::~linked_ptr()
{
TD(data);
delete this->next;
}
template<typename T, typename TD>
template<typename U, typename TU, class>
void linked_ptr<T, TD>::append(U data)
{
if (!this->next)
{
this->next = new linked_ptr<U, TU>(data);
this->next->previous = this;
return;
}
Node* t = this->next;
while(t->next != nullptr)
{
t = t->next;
}
t->next = new linked_ptr<U, TU>(data);
}
class foo
{
public:
virtual ~foo()
{
std::cout<<"destroyed foo\n";
};
virtual void print()
{
std::cout<<"foo\n";
}
};
class bar : public foo
{
public:
virtual ~bar()
{
std::cout<<"destroyed bar\n";
}
virtual void print()
{
std::cout<<"bar\n";
}
};
int main()
{
linked_ptr<foo*> list(new foo());
list.append(new bar());
list.append(new bar());
list.append(new bar());
}
Ly9odHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzI3NDMzNTMzL21ha2luZy10ZW1wbGF0ZS1mcm9tLWFueS1wYXJhbWV0ZXItYS1mcmllbmQtdG8tdGVtcGxhdGUtd2l0aC1vbmUtcGFyYW1ldGVyLWMvMjc0MzY2OTMjMjc0MzY2OTMKCgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CiNpbmNsdWRlIDxtZW1vcnk+CiNpbmNsdWRlIDxpb3N0cmVhbT4KCnRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lIFU+CnN0cnVjdCBpc19ub25fY2xhc3Nfc2FtZSA6IHB1YmxpYyBzdGQ6OmludGVncmFsX2NvbnN0YW50PGJvb2wsICghc3RkOjppc19iYXNlX29mPAogICAgICAgIHR5cGVuYW1lIHN0ZDo6cmVtb3ZlX3BvaW50ZXI8VD46OnR5cGUsCiAgICAgICAgdHlwZW5hbWUgc3RkOjpyZW1vdmVfcG9pbnRlcjxVPjo6dHlwZT46OnZhbHVlICYmCiAgICAgICAgc3RkOjppc19jb252ZXJ0aWJsZTxVLCBUPjo6dmFsdWUgJiYgc2l6ZW9mKFQpID49IHNpemVvZihVKSkgfHwKKHN0ZDo6aXNfY2xhc3M8VD46OnZhbHVlICYmIHN0ZDo6aXNfY2xhc3M8VT46OnZhbHVlICYmCiAhc3RkOjppc19wb2ludGVyPFQ+Ojp2YWx1ZSAmJiAhc3RkOjppc19wb2ludGVyPFU+Ojp2YWx1ZSAmJgogc3RkOjppc19zYW1lPFQsIFU+Ojp2YWx1ZSk+Cnt9OwoKdGVtcGxhdGU8dHlwZW5hbWUgVCwgdHlwZW5hbWUgVT4Kc3RydWN0IGlzX2NsYXNzX3NhbWUgOiBwdWJsaWMgc3RkOjppbnRlZ3JhbF9jb25zdGFudDxib29sLCBzdGQ6OmlzX2Jhc2Vfb2Y8CiAgICAgICAgdHlwZW5hbWUgc3RkOjpyZW1vdmVfcG9pbnRlcjxUPjo6dHlwZSwKICAgICAgICB0eXBlbmFtZSBzdGQ6OnJlbW92ZV9wb2ludGVyPFU+Ojp0eXBlPjo6dmFsdWUgJiYKICAgICAgICBzdGQ6OmlzX3BvaW50ZXI8VD46OnZhbHVlPgp7fTsKCgpjbGFzcyBOb2RlCnsKcHJvdGVjdGVkOgogICAgTm9kZSogcHJldmlvdXM7CiAgICBOb2RlKiBuZXh0OwoKICAgIE5vZGUoKSA6IHByZXZpb3VzKG51bGxwdHIpLCBuZXh0KG51bGxwdHIpIHt9CgogICAgdGVtcGxhdGU8Y2xhc3MgVCwgY2xhc3MgVEQ+CiAgICBmcmllbmQgY2xhc3MgbGlua2VkX3B0cjsKCnB1YmxpYzoKICAgIHZpcnR1YWwgfk5vZGUoKSB7fQoKfTsKCnRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lIFREID0gdHlwZW5hbWUgc3RkOjpyZW1vdmVfcG9pbnRlcjxUPjo6dHlwZT4KY2xhc3MgbGlua2VkX3B0ciA6IHB1YmxpYyBOb2RlCnsKcHJpdmF0ZToKICAgIHRlbXBsYXRlPGNsYXNzLCBjbGFzcz4gZnJpZW5kIGNsYXNzIGxpbmtlZF9wdHI7IC8qKiBBY2Nlc3MgZnJpZW5kIGxldmVsICoqLwogICAgVCBkYXRhOwoKcHVibGljOgoKICAgIHRlbXBsYXRlPGNsYXNzIFUsIHR5cGVuYW1lIFRVID0gdHlwZW5hbWUgc3RkOjpyZW1vdmVfcG9pbnRlcjxVPjo6dHlwZSwgdHlwZW5hbWUgPSB0eXBlbmFtZSBzdGQ6OmVuYWJsZV9pZjxpc19ub25fY2xhc3Nfc2FtZTxULCBVPjo6dmFsdWUgfHwgaXNfY2xhc3Nfc2FtZTxULCBVPjo6dmFsdWUsIFU+Ojp0eXBlPgogICAgbGlua2VkX3B0cihVIGRhdGEpIDogZGF0YShkYXRhKSB7fQogICAgfmxpbmtlZF9wdHIoKTsKCiAgICB0ZW1wbGF0ZTxjbGFzcyBVLCB0eXBlbmFtZSBUVSA9IHR5cGVuYW1lIHN0ZDo6cmVtb3ZlX3BvaW50ZXI8VT46OnR5cGUsIHR5cGVuYW1lID0gdHlwZW5hbWUgc3RkOjplbmFibGVfaWY8aXNfbm9uX2NsYXNzX3NhbWU8VCwgVT46OnZhbHVlIHx8IGlzX2NsYXNzX3NhbWU8VCwgVT46OnZhbHVlLCBVPjo6dHlwZT4KICAgIHZvaWQgc2V0RGF0YShVIGRhdGEpCiAgICB7CiAgICAgICAgdGhpcy0+ZGF0YSA9IGRhdGE7CiAgICB9CgogICAgdGVtcGxhdGU8Y2xhc3MgVSwgdHlwZW5hbWUgVFUgPSB0eXBlbmFtZSBzdGQ6OnJlbW92ZV9wb2ludGVyPFU+Ojp0eXBlLCB0eXBlbmFtZSA9IHR5cGVuYW1lIHN0ZDo6ZW5hYmxlX2lmPGlzX25vbl9jbGFzc19zYW1lPFQsIFU+Ojp2YWx1ZSB8fCBpc19jbGFzc19zYW1lPFQsIFU+Ojp2YWx1ZSwgVT46OnR5cGU+CiAgICB2b2lkIGFwcGVuZChVIGRhdGEpOwp9OwoKdGVtcGxhdGU8dHlwZW5hbWUgVCwgdHlwZW5hbWUgVEQ+CmxpbmtlZF9wdHI8VCwgVEQ+Ojp+bGlua2VkX3B0cigpCnsKICAgIFREKGRhdGEpOwogICAgZGVsZXRlIHRoaXMtPm5leHQ7Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lIFREPgp0ZW1wbGF0ZTx0eXBlbmFtZSBVLCB0eXBlbmFtZSBUVSwgY2xhc3M+CnZvaWQgbGlua2VkX3B0cjxULCBURD46OmFwcGVuZChVIGRhdGEpCnsKICAgIGlmICghdGhpcy0+bmV4dCkKICAgIHsKICAgICAgICB0aGlzLT5uZXh0ID0gbmV3IGxpbmtlZF9wdHI8VSwgVFU+KGRhdGEpOwogICAgICAgIHRoaXMtPm5leHQtPnByZXZpb3VzID0gdGhpczsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgTm9kZSogdCA9IHRoaXMtPm5leHQ7CiAgICB3aGlsZSh0LT5uZXh0ICE9IG51bGxwdHIpCiAgICB7CiAgICAgICAgdCA9IHQtPm5leHQ7CiAgICB9CgogICAgdC0+bmV4dCA9IG5ldyBsaW5rZWRfcHRyPFUsIFRVPihkYXRhKTsKfQoKCgoKY2xhc3MgZm9vCnsKcHVibGljOgogICAgdmlydHVhbCB+Zm9vKCkKICAgIHsKICAgICAgICBzdGQ6OmNvdXQ8PCJkZXN0cm95ZWQgZm9vXG4iOwogICAgfTsKCiAgICB2aXJ0dWFsIHZvaWQgcHJpbnQoKQogICAgewogICAgICAgIHN0ZDo6Y291dDw8ImZvb1xuIjsKICAgIH0KfTsKCmNsYXNzIGJhciA6IHB1YmxpYyBmb28KewpwdWJsaWM6CiAgICB2aXJ0dWFsIH5iYXIoKQogICAgewogICAgICAgIHN0ZDo6Y291dDw8ImRlc3Ryb3llZCBiYXJcbiI7CiAgICB9CgogICAgdmlydHVhbCB2b2lkIHByaW50KCkKICAgIHsKICAgICAgICBzdGQ6OmNvdXQ8PCJiYXJcbiI7CiAgICB9Cn07CgppbnQgbWFpbigpCnsKICAgIGxpbmtlZF9wdHI8Zm9vKj4gbGlzdChuZXcgZm9vKCkpOwogICAgbGlzdC5hcHBlbmQobmV3IGJhcigpKTsKICAgIGxpc3QuYXBwZW5kKG5ldyBiYXIoKSk7CiAgICBsaXN0LmFwcGVuZChuZXcgYmFyKCkpOwp9