#include <iostream>
// test stubs:
template<typename... Ts>
using UPtr = int;
template<typename... Ts>
using SPtr = double;
template<typename T, typename...TA>
UPtr<T,TA...> makeUniquePtr() {
std::cout << "makeUniquePtr\n";
return {};
}
template<typename T, typename...TA>
SPtr<T,TA...> makeSharedPtr() {
std::cout << "makeSharedPtr\n";
return {};
}
struct unique_ptr_maker {
template<typename T, typename...TA, typename...Args>
static UPtr<T, TA...> make(Args&&...args) {
return makeUniquePtr<T, TA...>( std::forward<Args>(args)... );
}
};
struct shared_ptr_maker {
template<typename T, typename...TA, typename...Args>
static SPtr<T, TA...> make(Args&&...args) {
return makeSharedPtr<T, TA...>( std::forward<Args>(args)... );
}
};
template<typename maker, class T, class... TA> void func() {
std::cout << "func\n";
maker::template make<T, TA...>();
}
template<class T, class... TA> void implementation1()
{
func<unique_ptr_maker, T, TA...>();
}
template<class T, class... TA> void implementation2()
{
func<shared_ptr_maker, T, TA...>();
}
int main() {
implementation1<int, double>();
implementation2<int, char>();
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKICAgIC8vIHRlc3Qgc3R1YnM6CiAgICB0ZW1wbGF0ZTx0eXBlbmFtZS4uLiBUcz4KICAgIHVzaW5nIFVQdHIgPSBpbnQ7CiAgICB0ZW1wbGF0ZTx0eXBlbmFtZS4uLiBUcz4KICAgIHVzaW5nIFNQdHIgPSBkb3VibGU7CiAgICAKICAgIHRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lLi4uVEE+CiAgICBVUHRyPFQsVEEuLi4+IG1ha2VVbmlxdWVQdHIoKSB7CiAgICAJc3RkOjpjb3V0IDw8ICJtYWtlVW5pcXVlUHRyXG4iOwogICAgCXJldHVybiB7fTsKICAgIH0KICAgIHRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lLi4uVEE+CiAgICBTUHRyPFQsVEEuLi4+IG1ha2VTaGFyZWRQdHIoKSB7CiAgICAJc3RkOjpjb3V0IDw8ICJtYWtlU2hhcmVkUHRyXG4iOwogICAgCXJldHVybiB7fTsKICAgIH0KICAgIAogICAgc3RydWN0IHVuaXF1ZV9wdHJfbWFrZXIgewogICAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBULCB0eXBlbmFtZS4uLlRBLCB0eXBlbmFtZS4uLkFyZ3M+CiAgICAgIHN0YXRpYyBVUHRyPFQsIFRBLi4uPiBtYWtlKEFyZ3MmJi4uLmFyZ3MpIHsKICAgICAgICByZXR1cm4gbWFrZVVuaXF1ZVB0cjxULCBUQS4uLj4oIHN0ZDo6Zm9yd2FyZDxBcmdzPihhcmdzKS4uLiApOwogICAgICB9CiAgICB9OwogICAgc3RydWN0IHNoYXJlZF9wdHJfbWFrZXIgewogICAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBULCB0eXBlbmFtZS4uLlRBLCB0eXBlbmFtZS4uLkFyZ3M+CiAgICAgIHN0YXRpYyBTUHRyPFQsIFRBLi4uPiBtYWtlKEFyZ3MmJi4uLmFyZ3MpIHsKICAgICAgICByZXR1cm4gbWFrZVNoYXJlZFB0cjxULCBUQS4uLj4oIHN0ZDo6Zm9yd2FyZDxBcmdzPihhcmdzKS4uLiApOwogICAgICB9CiAgICB9OwogICAgCnRlbXBsYXRlPHR5cGVuYW1lIG1ha2VyLCBjbGFzcyBULCBjbGFzcy4uLiBUQT4gdm9pZCBmdW5jKCkgewoJc3RkOjpjb3V0IDw8ICJmdW5jXG4iOwoJbWFrZXI6OnRlbXBsYXRlIG1ha2U8VCwgVEEuLi4+KCk7Cn0KCnRlbXBsYXRlPGNsYXNzIFQsIGNsYXNzLi4uIFRBPiB2b2lkIGltcGxlbWVudGF0aW9uMSgpCnsKCWZ1bmM8dW5pcXVlX3B0cl9tYWtlciwgVCwgVEEuLi4+KCk7Cn0KdGVtcGxhdGU8Y2xhc3MgVCwgY2xhc3MuLi4gVEE+IHZvaWQgaW1wbGVtZW50YXRpb24yKCkKewoJZnVuYzxzaGFyZWRfcHRyX21ha2VyLCBULCBUQS4uLj4oKTsKfQppbnQgbWFpbigpIHsKCWltcGxlbWVudGF0aW9uMTxpbnQsIGRvdWJsZT4oKTsKCWltcGxlbWVudGF0aW9uMjxpbnQsIGNoYXI+KCk7CglyZXR1cm4gMDsKfQ==