#include <iostream>
#include <type_traits>
template<typename T>
class ptr {
T* m_ptr;
public:
ptr(T* a_ptr) : m_ptr(a_ptr) {}
template<typename U = T>
typename
std::enable_if<!std::is_same<U, void>::value, U&>::type
operator * () const { return *m_ptr; };
};
int main()
{
int i = 12345;
ptr<int> ptr_i(&i);
std::cout << *ptr_i; // OK
ptr<void> ptr_i2(&i);
std::cout << *ptr_i2; // ERROR
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBUPgpjbGFzcyBwdHIgewoJVCogbV9wdHI7CiAgICBwdWJsaWM6CgkJcHRyKFQqIGFfcHRyKSA6IG1fcHRyKGFfcHRyKSB7fQoKCQl0ZW1wbGF0ZTx0eXBlbmFtZSBVID0gVD4KCQl0eXBlbmFtZQoJCQlzdGQ6OmVuYWJsZV9pZjwhc3RkOjppc19zYW1lPFUsIHZvaWQ+Ojp2YWx1ZSwgVSY+Ojp0eXBlCgkJb3BlcmF0b3IgKiAoKSBjb25zdCB7IHJldHVybiAqbV9wdHI7IH07Cn07CgppbnQgbWFpbigpCnsKCWludCBpID0gMTIzNDU7CglwdHI8aW50PiBwdHJfaSgmaSk7CglzdGQ6OmNvdXQgPDwgKnB0cl9pOyAvLyBPSwoKCXB0cjx2b2lkPiBwdHJfaTIoJmkpOwoJc3RkOjpjb3V0IDw8ICpwdHJfaTI7IC8vIEVSUk9SCgkKCXJldHVybiAwOwp9
prog.cpp: In function ‘int main()’:
prog.cpp:23:15: error: no match for ‘operator*’ (operand type is ‘ptr<void>’)
std::cout << *ptr_i2; // ERROR
^~~~~~~
prog.cpp:13:3: note: candidate: ‘template<class U> typename std::enable_if<(! std::is_same<U, void>::value), U&>::type ptr<T>::operator*() const [with U = U; T = void]’
operator * () const { return *m_ptr; };
^~~~~~~~
prog.cpp:13:3: note: template argument deduction/substitution failed:
prog.cpp: In substitution of ‘template<class U> typename std::enable_if<(! std::is_same<U, void>::value), U&>::type ptr<void>::operator*<U>() const [with U = void]’:
prog.cpp:23:16: required from here
prog.cpp:13:3: error: forming reference to void