#include <iostream>
#include <string>
#include <cstdlib>
#define P(x) std::cout<<x<<std::endl
struct Scalar { std::string data = "scalar"; };
struct Array { std::string data = "array"; };
template<typename ReturnT = void>
ReturnT test() {}
template<>
void test() { P("param: void, return: void"); }
template<>
Scalar test() { P("param: void, return: scalar"); return Scalar(); }
template<>
Array test() { P("param: void, return: array"); return Array(); }
template<typename ReturnT = void, typename ParamT>
ReturnT test(ParamT x) {}
template<>
void test(Scalar x) { P("param: scalar, return: void"); }
template<>
void test(Array x) { P("param: array, return: void"); }
template<>
Scalar test(Scalar x) { P("param: scalar, return: scalar"); return Scalar(); }
template<>
Array test(Array x) { P("param: array, return: array"); return Array(); }
int main()
{
test();
Scalar a = test<Scalar>();
Array b = test<Array>();
Scalar c = test<Scalar, Scalar>(Scalar());
Array d = test<Array, Array>(Array());
test<void, Scalar>(Scalar());
test<void, Array>(Array());
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8c3RyaW5nPgojaW5jbHVkZSA8Y3N0ZGxpYj4KI2RlZmluZSBQKHgpIHN0ZDo6Y291dDw8eDw8c3RkOjplbmRsCgpzdHJ1Y3QgU2NhbGFyIHsgc3RkOjpzdHJpbmcgZGF0YSA9ICJzY2FsYXIiOyB9OwpzdHJ1Y3QgQXJyYXkgIHsgc3RkOjpzdHJpbmcgZGF0YSA9ICJhcnJheSI7ICB9OwoKCnRlbXBsYXRlPHR5cGVuYW1lIFJldHVyblQgPSB2b2lkPgpSZXR1cm5UIHRlc3QoKSB7fQoKdGVtcGxhdGU8Pgp2b2lkIHRlc3QoKSB7IFAoInBhcmFtOiB2b2lkLCByZXR1cm46IHZvaWQiKTsgfQoKdGVtcGxhdGU8PiAKU2NhbGFyIHRlc3QoKSB7IFAoInBhcmFtOiB2b2lkLCByZXR1cm46IHNjYWxhciIpOyByZXR1cm4gU2NhbGFyKCk7IH0KCnRlbXBsYXRlPD4gCkFycmF5IHRlc3QoKSAgeyBQKCJwYXJhbTogdm9pZCwgcmV0dXJuOiBhcnJheSIpOyAgcmV0dXJuIEFycmF5KCk7IH0KCgp0ZW1wbGF0ZTx0eXBlbmFtZSBSZXR1cm5UID0gdm9pZCwgdHlwZW5hbWUgUGFyYW1UPgpSZXR1cm5UIHRlc3QoUGFyYW1UIHgpIHt9Cgp0ZW1wbGF0ZTw+CnZvaWQgdGVzdChTY2FsYXIgeCkgICB7IFAoInBhcmFtOiBzY2FsYXIsIHJldHVybjogdm9pZCIpOyB9Cgp0ZW1wbGF0ZTw+CnZvaWQgdGVzdChBcnJheSB4KSAgICB7IFAoInBhcmFtOiBhcnJheSwgcmV0dXJuOiB2b2lkIik7IH0KCnRlbXBsYXRlPD4gClNjYWxhciB0ZXN0KFNjYWxhciB4KSB7IFAoInBhcmFtOiBzY2FsYXIsIHJldHVybjogc2NhbGFyIik7ICByZXR1cm4gU2NhbGFyKCk7IH0KCnRlbXBsYXRlPD4gCkFycmF5IHRlc3QoQXJyYXkgeCkgICB7IFAoInBhcmFtOiBhcnJheSwgcmV0dXJuOiBhcnJheSIpOyAgICByZXR1cm4gQXJyYXkoKTsgfQoKCmludCBtYWluKCkKewogICB0ZXN0KCk7CiAgIFNjYWxhciBhID0gdGVzdDxTY2FsYXI+KCk7CiAgIEFycmF5ICBiID0gdGVzdDxBcnJheT4oKTsKICAgU2NhbGFyIGMgPSB0ZXN0PFNjYWxhciwgU2NhbGFyPihTY2FsYXIoKSk7CiAgIEFycmF5ICBkID0gdGVzdDxBcnJheSwgQXJyYXk+KEFycmF5KCkpOwogICB0ZXN0PHZvaWQsIFNjYWxhcj4oU2NhbGFyKCkpOwogICB0ZXN0PHZvaWQsIEFycmF5PihBcnJheSgpKTsKfQoKCgo=
param: void, return: void
param: void, return: scalar
param: void, return: array
param: scalar, return: scalar
param: array, return: array
param: scalar, return: void
param: array, return: void