#include <type_traits>
template <int...> struct indexes {};
namespace {
template<int a, int... other>
constexpr indexes<a, other...> combine(indexes<other...> deduce);
template<int a, int b, typename Enable = void> struct expand_span_; // primary
template<int a, int b>
struct expand_span_<a, b, typename std::enable_if< (a==b), void >::type> {
static constexpr indexes<a> dispatch();
};
template<int a, int b>
struct expand_span_<a, b, typename std::enable_if< (a<b), void >::type> {
static constexpr decltype(combine<a>(expand_span_<a+1, b>::dispatch()))
dispatch();
};
template<int a, int b>
constexpr auto expand_span() -> decltype(expand_span_<a,b>::dispatch());
}
template <int a, int b> using span = decltype(expand_span<a,b>());
////////////////////////////////////////////////////////////////
// using indirect template arguments
template<typename> struct indirect_work { };
void test_indirect()
{
indirect_work<indexes<1,2,3,4>> x;
indirect_work<span<1,4>> y;
x = y; // x and y are of identical types
static_assert(std::is_same<indexes<1,2,3,4>, span<1,4>>::value, "fact check");
}
////////////////////////////////////////////////////////////////
// using direct template arguments
template<int...> struct direct_work { };
// deduction alias:
template<int... direct> constexpr direct_work<direct...> deduction_helper(indexes<direct...>);
template <typename Idx> using deduce = decltype(deduction_helper(Idx{}));
void test_direct()
{
direct_work<1,2,3,4> x;
deduce<indexes<1,2,3,4>> y;
deduce<span<1,4>> z;
static_assert(std::is_same<decltype(x), decltype(y)>::value, "fact check");
static_assert(std::is_same<decltype(x), decltype(z)>::value, "fact check");
}
int main()
{
test_indirect();
test_direct();
}
I2luY2x1ZGUgPHR5cGVfdHJhaXRzPgoKdGVtcGxhdGUgPGludC4uLj4gc3RydWN0IGluZGV4ZXMge307CgpuYW1lc3BhY2UgewogICAgdGVtcGxhdGU8aW50IGEsIGludC4uLiBvdGhlcj4KICAgICAgICBjb25zdGV4cHIgaW5kZXhlczxhLCBvdGhlci4uLj4gY29tYmluZShpbmRleGVzPG90aGVyLi4uPiBkZWR1Y2UpOwoKICAgIHRlbXBsYXRlPGludCBhLCBpbnQgYiwgdHlwZW5hbWUgRW5hYmxlID0gdm9pZD4gc3RydWN0IGV4cGFuZF9zcGFuXzsgLy8gcHJpbWFyeQoKICAgIHRlbXBsYXRlPGludCBhLCBpbnQgYj4KICAgIHN0cnVjdCBleHBhbmRfc3Bhbl88YSwgYiwgdHlwZW5hbWUgc3RkOjplbmFibGVfaWY8IChhPT1iKSwgdm9pZCA+Ojp0eXBlPiB7CiAgICAgICAgc3RhdGljIGNvbnN0ZXhwciBpbmRleGVzPGE+IGRpc3BhdGNoKCk7CiAgICB9OwoKICAgIHRlbXBsYXRlPGludCBhLCBpbnQgYj4KICAgIHN0cnVjdCBleHBhbmRfc3Bhbl88YSwgYiwgdHlwZW5hbWUgc3RkOjplbmFibGVfaWY8IChhPGIpLCB2b2lkID46OnR5cGU+IHsKICAgICAgICBzdGF0aWMgY29uc3RleHByIGRlY2x0eXBlKGNvbWJpbmU8YT4oZXhwYW5kX3NwYW5fPGErMSwgYj46OmRpc3BhdGNoKCkpKSAKICAgICAgICAgICAgZGlzcGF0Y2goKTsKICAgIH07CgogICAgdGVtcGxhdGU8aW50IGEsIGludCBiPgogICAgY29uc3RleHByIGF1dG8gZXhwYW5kX3NwYW4oKSAtPiBkZWNsdHlwZShleHBhbmRfc3Bhbl88YSxiPjo6ZGlzcGF0Y2goKSk7Cn0KCnRlbXBsYXRlIDxpbnQgYSwgaW50IGI+IHVzaW5nIHNwYW4gPSBkZWNsdHlwZShleHBhbmRfc3BhbjxhLGI+KCkpOwoKLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwovLyB1c2luZyBpbmRpcmVjdCB0ZW1wbGF0ZSBhcmd1bWVudHMKdGVtcGxhdGU8dHlwZW5hbWU+IHN0cnVjdCBpbmRpcmVjdF93b3JrIHsgfTsKCnZvaWQgdGVzdF9pbmRpcmVjdCgpCnsKICAgIGluZGlyZWN0X3dvcms8aW5kZXhlczwxLDIsMyw0Pj4geDsKICAgIGluZGlyZWN0X3dvcms8c3BhbjwxLDQ+PiAgICAgICAgeTsKCiAgICB4ID0geTsgLy8geCBhbmQgeSBhcmUgb2YgaWRlbnRpY2FsIHR5cGVzCiAgICBzdGF0aWNfYXNzZXJ0KHN0ZDo6aXNfc2FtZTxpbmRleGVzPDEsMiwzLDQ+LCBzcGFuPDEsND4+Ojp2YWx1ZSwgImZhY3QgY2hlY2siKTsKfQoKLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwovLyB1c2luZyBkaXJlY3QgdGVtcGxhdGUgYXJndW1lbnRzCnRlbXBsYXRlPGludC4uLj4gc3RydWN0IGRpcmVjdF93b3JrIHsgfTsKCi8vIGRlZHVjdGlvbiBhbGlhczoKdGVtcGxhdGU8aW50Li4uIGRpcmVjdD4gY29uc3RleHByIGRpcmVjdF93b3JrPGRpcmVjdC4uLj4gZGVkdWN0aW9uX2hlbHBlcihpbmRleGVzPGRpcmVjdC4uLj4pOwp0ZW1wbGF0ZSA8dHlwZW5hbWUgSWR4PiB1c2luZyBkZWR1Y2UgPSBkZWNsdHlwZShkZWR1Y3Rpb25faGVscGVyKElkeHt9KSk7Cgp2b2lkIHRlc3RfZGlyZWN0KCkKewogICAgZGlyZWN0X3dvcms8MSwyLDMsND4geDsKICAgIGRlZHVjZTxpbmRleGVzPDEsMiwzLDQ+PiB5OwogICAgZGVkdWNlPHNwYW48MSw0Pj4gejsKCiAgICBzdGF0aWNfYXNzZXJ0KHN0ZDo6aXNfc2FtZTxkZWNsdHlwZSh4KSwgZGVjbHR5cGUoeSk+Ojp2YWx1ZSwgImZhY3QgY2hlY2siKTsKICAgIHN0YXRpY19hc3NlcnQoc3RkOjppc19zYW1lPGRlY2x0eXBlKHgpLCBkZWNsdHlwZSh6KT46OnZhbHVlLCAiZmFjdCBjaGVjayIpOwp9CgppbnQgbWFpbigpCnsKICAgIHRlc3RfaW5kaXJlY3QoKTsKICAgIHRlc3RfZGlyZWN0KCk7Cn0K