#include <iostream>
#include <typeinfo>
#include <memory>
struct nil { };
//スマートポインタを生ポインタと同様に扱うための変換
//int -> nil*, int* -> int*, smart_ptr<int> -> int*
template <typename T>
class dereferencable {
static T getT();
template <typename U>
static std::true_type test1(U&& u, decltype(*u, 0) = 0); //本来はtest1だけでOKのはず
template <typename U>
static std::true_type test2(U&& u, typename std::enable_if<std::is_same< //workaround for VC2012
typename std::remove_cv<typename std::remove_reference<decltype(&*u)>::type>::type,
typename std::remove_cv<typename std::remove_reference<decltype(&u)>::type>::type
>::value>::type* = 0 );
static std::false_type test1(...);
static std::false_type test2(...);
typedef decltype(test1(getT())) T1;
typedef decltype(test2(getT())) T2;
typedef typename std::conditional<T1::value && !T2::value, T, nil*>::type psp_type;
static psp_type getPSP();
public:
static const bool value = (T1::value && !T2::value); //int -> false, int* -> true, s_ptr<int> -> true
typedef decltype(&*getPSP()) p_type; //int -> nil*, int* -> int*, s_ptr<int> -> int*
};
int main()
{
int v=9;
int* p = &v;
std::unique_ptr<int> sp(new int(14312421));
std::cout << dereferencable<decltype(v)>::value << std::endl;
std::cout << dereferencable<decltype(p)>::value << std::endl;
std::cout << dereferencable<decltype(sp)>::value << std::endl;
std::cout << typeid(nil*).name() << " : " <<
typeid(dereferencable<decltype(v)>::p_type).name() << std::endl;
std::cout << typeid(int*).name() << " : " <<
typeid(dereferencable<decltype(p)>::p_type).name() << std::endl;
std::cout << typeid(int*).name() << " : " <<
typeid(dereferencable<decltype(sp)>::p_type).name() << std::endl;
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZWluZm8+IAojaW5jbHVkZSA8bWVtb3J5PgoKc3RydWN0IG5pbAkJeyB9OwoKLy/jgrnjg57jg7zjg4jjg53jgqTjg7Pjgr/jgpLnlJ/jg53jgqTjg7Pjgr/jgajlkIzmp5jjgavmibHjgYbjgZ/jgoHjga7lpInmj5sKLy9pbnQgLT4gbmlsKiwgIGludCogLT4gaW50KiwgIHNtYXJ0X3B0cjxpbnQ+IC0+IGludCoKdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CgljbGFzcyBkZXJlZmVyZW5jYWJsZQl7CgkJc3RhdGljIFQgZ2V0VCgpOwoJCXRlbXBsYXRlIDx0eXBlbmFtZSBVPgoJCQlzdGF0aWMgc3RkOjp0cnVlX3R5cGUgdGVzdDEoVSYmIHUsIGRlY2x0eXBlKCp1LCAwKSA9IDApOwkvL+acrOadpeOBr3Rlc3Qx44Gg44GR44GnT0vjga7jga/jgZoKCQl0ZW1wbGF0ZSA8dHlwZW5hbWUgVT4KCQkJc3RhdGljIHN0ZDo6dHJ1ZV90eXBlIHRlc3QyKFUmJiB1LCB0eXBlbmFtZSBzdGQ6OmVuYWJsZV9pZjxzdGQ6OmlzX3NhbWU8CS8vd29ya2Fyb3VuZCBmb3IgVkMyMDEyCgkJCQkJCQkJdHlwZW5hbWUgc3RkOjpyZW1vdmVfY3Y8dHlwZW5hbWUgc3RkOjpyZW1vdmVfcmVmZXJlbmNlPGRlY2x0eXBlKCYqdSk+Ojp0eXBlPjo6dHlwZSwKCQkJCQkJCQl0eXBlbmFtZSBzdGQ6OnJlbW92ZV9jdjx0eXBlbmFtZSBzdGQ6OnJlbW92ZV9yZWZlcmVuY2U8ZGVjbHR5cGUoJnUpPjo6dHlwZT46OnR5cGUKCQkJCQkJCQkJCT46OnZhbHVlPjo6dHlwZSogPSAwICk7CgkJc3RhdGljIHN0ZDo6ZmFsc2VfdHlwZQl0ZXN0MSguLi4pOwoJCXN0YXRpYyBzdGQ6OmZhbHNlX3R5cGUJdGVzdDIoLi4uKTsKCQl0eXBlZGVmIGRlY2x0eXBlKHRlc3QxKGdldFQoKSkpCVQxOwoJCXR5cGVkZWYgZGVjbHR5cGUodGVzdDIoZ2V0VCgpKSkJVDI7CgkJdHlwZWRlZiB0eXBlbmFtZSBzdGQ6OmNvbmRpdGlvbmFsPFQxOjp2YWx1ZSAmJiAhVDI6OnZhbHVlLCBULCBuaWwqPjo6dHlwZSAgcHNwX3R5cGU7IAoJCXN0YXRpYyBwc3BfdHlwZQlnZXRQU1AoKTsKCXB1YmxpYzoKCQlzdGF0aWMgY29uc3QgYm9vbCB2YWx1ZSA9IChUMTo6dmFsdWUgJiYgIVQyOjp2YWx1ZSk7CS8vaW50IC0+IGZhbHNlLCAgaW50KiAtPiB0cnVlLCAgc19wdHI8aW50PiAtPiB0cnVlCgkJdHlwZWRlZiBkZWNsdHlwZSgmKmdldFBTUCgpKQlwX3R5cGU7CQkvL2ludCAtPiBuaWwqLCAgaW50KiAtPiBpbnQqLCAgc19wdHI8aW50PiAtPiBpbnQqCgl9OwoKIGludCAgbWFpbigpCnsKCWludCB2PTk7CglpbnQqIHAgPSAmdjsKCXN0ZDo6dW5pcXVlX3B0cjxpbnQ+IHNwKG5ldyBpbnQoMTQzMTI0MjEpKTsKCglzdGQ6OmNvdXQgPDwgZGVyZWZlcmVuY2FibGU8ZGVjbHR5cGUodik+Ojp2YWx1ZSA8PCBzdGQ6OmVuZGw7CglzdGQ6OmNvdXQgPDwgZGVyZWZlcmVuY2FibGU8ZGVjbHR5cGUocCk+Ojp2YWx1ZSA8PCBzdGQ6OmVuZGw7CglzdGQ6OmNvdXQgPDwgZGVyZWZlcmVuY2FibGU8ZGVjbHR5cGUoc3ApPjo6dmFsdWUgPDwgc3RkOjplbmRsOwoJCglzdGQ6OmNvdXQgPDwgdHlwZWlkKG5pbCopLm5hbWUoKSA8PCAiIDogIiA8PAoJCXR5cGVpZChkZXJlZmVyZW5jYWJsZTxkZWNsdHlwZSh2KT46OnBfdHlwZSkubmFtZSgpIDw8IHN0ZDo6ZW5kbDsKCXN0ZDo6Y291dCA8PCB0eXBlaWQoaW50KikubmFtZSgpIDw8ICIgOiAiIDw8CgkJdHlwZWlkKGRlcmVmZXJlbmNhYmxlPGRlY2x0eXBlKHApPjo6cF90eXBlKS5uYW1lKCkgPDwgc3RkOjplbmRsOwoJc3RkOjpjb3V0IDw8IHR5cGVpZChpbnQqKS5uYW1lKCkgPDwgIiA6ICIgPDwKCQl0eXBlaWQoZGVyZWZlcmVuY2FibGU8ZGVjbHR5cGUoc3ApPjo6cF90eXBlKS5uYW1lKCkgPDwgc3RkOjplbmRsOwoKCglyZXR1cm4gMDsKfQ==