#include <cstdint>
// List of factors
template<std::intmax_t...>
struct factors { };
// Declaration
template<bool no_remainder, std::intmax_t Value, std::intmax_t Divisor, std::intmax_t ... Primes>
struct factorization_remove_repeated;
template<bool no_remainder, std::intmax_t Value, std::intmax_t Divisor, std::intmax_t ... Primes>
struct factorization_check;
// Remove repeated factors without appending to primes list
template<std::intmax_t Value, std::intmax_t Divisor, std::intmax_t ... Primes>
struct factorization_remove_repeated<false, Value, Divisor, Primes...>
{
typedef typename factorization_check<Value % (Divisor + 1) == 0, Value, Divisor + 1, Primes...>::type type;
};
template<std::intmax_t Value, std::intmax_t Divisor, std::intmax_t ... Primes>
struct factorization_remove_repeated<true, Value, Divisor, Primes...>
{
typedef typename factorization_remove_repeated<(Value / Divisor) % Divisor == 0, Value / Divisor, Divisor, Primes...>::type type;
};
template<std::intmax_t Value, std::intmax_t Divisor, std::intmax_t ... Primes>
struct factorization_check<false, Value, Divisor, Primes...>
{
typedef typename factorization_check<Value % (Divisor + 1) == 0, Value, Divisor + 1, Primes...>::type type;
};
template<std::intmax_t Value, std::intmax_t Divisor, std::intmax_t ... Primes>
struct factorization_check<true, Value, Divisor, Primes...>
{
typedef typename factorization_remove_repeated<(Value / Divisor) % Divisor == 0, Value / Divisor, Divisor, Primes..., Divisor>::type type;
};
template<std::intmax_t Divisor, std::intmax_t ... Primes>
struct factorization_remove_repeated<false, 1, Divisor, Primes...>
{
typedef factors<Primes...> type;
};
// Initial specialization
template<std::intmax_t Value>
struct factorization
{
typedef typename factorization_check<Value % 2 == 0, Value, 2>::type type;
};
#include <typeinfo>
#include <iostream>
// Main
int main()
{
typename factorization<18>::type x;
std::cout << typeid(x).name();
return 0;
}
I2luY2x1ZGUgPGNzdGRpbnQ+CgovLyBMaXN0IG9mIGZhY3RvcnMKdGVtcGxhdGU8c3RkOjppbnRtYXhfdC4uLj4gCnN0cnVjdCBmYWN0b3JzIHsgfTsKCi8vIERlY2xhcmF0aW9uCnRlbXBsYXRlPGJvb2wgbm9fcmVtYWluZGVyLCBzdGQ6OmludG1heF90IFZhbHVlLCBzdGQ6OmludG1heF90IERpdmlzb3IsIHN0ZDo6aW50bWF4X3QgLi4uIFByaW1lcz4gCnN0cnVjdCBmYWN0b3JpemF0aW9uX3JlbW92ZV9yZXBlYXRlZDsKdGVtcGxhdGU8Ym9vbCBub19yZW1haW5kZXIsIHN0ZDo6aW50bWF4X3QgVmFsdWUsIHN0ZDo6aW50bWF4X3QgRGl2aXNvciwgc3RkOjppbnRtYXhfdCAuLi4gUHJpbWVzPiAKc3RydWN0IGZhY3Rvcml6YXRpb25fY2hlY2s7CgovLyBSZW1vdmUgcmVwZWF0ZWQgZmFjdG9ycyB3aXRob3V0IGFwcGVuZGluZyB0byBwcmltZXMgbGlzdAp0ZW1wbGF0ZTxzdGQ6OmludG1heF90IFZhbHVlLCBzdGQ6OmludG1heF90IERpdmlzb3IsIHN0ZDo6aW50bWF4X3QgLi4uIFByaW1lcz4gCnN0cnVjdCBmYWN0b3JpemF0aW9uX3JlbW92ZV9yZXBlYXRlZDxmYWxzZSwgVmFsdWUsIERpdmlzb3IsIFByaW1lcy4uLj4KewogICAgdHlwZWRlZiB0eXBlbmFtZSBmYWN0b3JpemF0aW9uX2NoZWNrPFZhbHVlICUgKERpdmlzb3IgKyAxKSA9PSAwLCBWYWx1ZSwgRGl2aXNvciArIDEsIFByaW1lcy4uLj46OnR5cGUgdHlwZTsKfTsKCnRlbXBsYXRlPHN0ZDo6aW50bWF4X3QgVmFsdWUsIHN0ZDo6aW50bWF4X3QgRGl2aXNvciwgc3RkOjppbnRtYXhfdCAuLi4gUHJpbWVzPgpzdHJ1Y3QgZmFjdG9yaXphdGlvbl9yZW1vdmVfcmVwZWF0ZWQ8dHJ1ZSwgVmFsdWUsIERpdmlzb3IsIFByaW1lcy4uLj4KewogICAgdHlwZWRlZiB0eXBlbmFtZSBmYWN0b3JpemF0aW9uX3JlbW92ZV9yZXBlYXRlZDwoVmFsdWUgLyBEaXZpc29yKSAlIERpdmlzb3IgPT0gMCwgVmFsdWUgLyBEaXZpc29yLCBEaXZpc29yLCBQcmltZXMuLi4+Ojp0eXBlIHR5cGU7Cn07Cgp0ZW1wbGF0ZTxzdGQ6OmludG1heF90IFZhbHVlLCBzdGQ6OmludG1heF90IERpdmlzb3IsIHN0ZDo6aW50bWF4X3QgLi4uIFByaW1lcz4gCnN0cnVjdCBmYWN0b3JpemF0aW9uX2NoZWNrPGZhbHNlLCBWYWx1ZSwgRGl2aXNvciwgUHJpbWVzLi4uPgp7CiAgICB0eXBlZGVmIHR5cGVuYW1lIGZhY3Rvcml6YXRpb25fY2hlY2s8VmFsdWUgJSAoRGl2aXNvciArIDEpID09IDAsIFZhbHVlLCBEaXZpc29yICsgMSwgUHJpbWVzLi4uPjo6dHlwZSB0eXBlOwp9OwoKdGVtcGxhdGU8c3RkOjppbnRtYXhfdCBWYWx1ZSwgc3RkOjppbnRtYXhfdCBEaXZpc29yLCBzdGQ6OmludG1heF90IC4uLiBQcmltZXM+CnN0cnVjdCBmYWN0b3JpemF0aW9uX2NoZWNrPHRydWUsIFZhbHVlLCBEaXZpc29yLCBQcmltZXMuLi4+CnsKICAgIHR5cGVkZWYgdHlwZW5hbWUgZmFjdG9yaXphdGlvbl9yZW1vdmVfcmVwZWF0ZWQ8KFZhbHVlIC8gRGl2aXNvcikgJSBEaXZpc29yID09IDAsIFZhbHVlIC8gRGl2aXNvciwgRGl2aXNvciwgUHJpbWVzLi4uLCBEaXZpc29yPjo6dHlwZSB0eXBlOwp9OwoKdGVtcGxhdGU8c3RkOjppbnRtYXhfdCBEaXZpc29yLCBzdGQ6OmludG1heF90IC4uLiBQcmltZXM+IApzdHJ1Y3QgZmFjdG9yaXphdGlvbl9yZW1vdmVfcmVwZWF0ZWQ8ZmFsc2UsIDEsIERpdmlzb3IsIFByaW1lcy4uLj4KewogICAgdHlwZWRlZiBmYWN0b3JzPFByaW1lcy4uLj4gdHlwZTsKfTsKCi8vIEluaXRpYWwgc3BlY2lhbGl6YXRpb24KdGVtcGxhdGU8c3RkOjppbnRtYXhfdCBWYWx1ZT4gCnN0cnVjdCBmYWN0b3JpemF0aW9uCnsKICAgIHR5cGVkZWYgdHlwZW5hbWUgZmFjdG9yaXphdGlvbl9jaGVjazxWYWx1ZSAlIDIgPT0gMCwgVmFsdWUsIDI+Ojp0eXBlIHR5cGU7Cn07CgojaW5jbHVkZSA8dHlwZWluZm8+CiNpbmNsdWRlIDxpb3N0cmVhbT4KLy8gTWFpbgppbnQgbWFpbigpCnsKCXR5cGVuYW1lIGZhY3Rvcml6YXRpb248MTg+Ojp0eXBlIHg7CglzdGQ6OmNvdXQgPDwgdHlwZWlkKHgpLm5hbWUoKTsKCXJldHVybiAwOwp9