#include <iostream>
template<typename T>
constexpr T shift_left(const T value) { return value << 1; }
template<typename T>
constexpr T increment(const T value) { return value + 1; }
template<typename T>
constexpr T bicrement(const T value) { return value + 2; }
template<typename T>
constexpr T test(const T value) { return bicrement(shift_left(increment(value))); }
template <typename T, T(*INC)(const T), T start = {}>
struct managed_enum
{
enum
{
a = start,
b = INC(a),
c = INC(b),
};
};
template <typename T, T(*INC)(const T), T start = {}>
struct managed_strong_enum
{
enum class value : T
{
a = start,
b = INC(a),
c = INC(b),
};
};
int main()
{
using shifted = managed_enum<int, shift_left<int>, 1>;
using increment = managed_enum<int, increment<int>>;
using bicrement = managed_enum<int, bicrement<int>>;
using test = managed_strong_enum<int, test<int>, 5>;
std::cout << "[<< 1] -> a: " << shifted::a
<< "\tb: " << shifted::b
<< "\tc: " << shifted::c << '\n';
std::cout << "[ +1 ] -> a: " << increment::a
<< "\tb: " << increment::b
<< "\tc: " << increment::c << '\n';
std::cout << "[ +2 ] -> a: " << bicrement::a
<< "\tb: " << bicrement::b
<< "\tc: " << bicrement::c << '\n';
std::cout << "[test] -> a: " << int(test::value::a)
<< "\tb: " << int(test::value::b)
<< "\tc: " << int(test::value::c) << '\n';
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKdGVtcGxhdGU8dHlwZW5hbWUgVD4KY29uc3RleHByIFQgc2hpZnRfbGVmdChjb25zdCBUIHZhbHVlKSB7IHJldHVybiB2YWx1ZSA8PCAxOyB9Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBUPgpjb25zdGV4cHIgVCBpbmNyZW1lbnQoY29uc3QgVCB2YWx1ZSkgeyByZXR1cm4gdmFsdWUgKyAxOyB9Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBUPgpjb25zdGV4cHIgVCBiaWNyZW1lbnQoY29uc3QgVCB2YWx1ZSkgeyByZXR1cm4gdmFsdWUgKyAyOyB9Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBUPgpjb25zdGV4cHIgVCB0ZXN0KGNvbnN0IFQgdmFsdWUpIHsgcmV0dXJuIGJpY3JlbWVudChzaGlmdF9sZWZ0KGluY3JlbWVudCh2YWx1ZSkpKTsgfQoKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIFQoKklOQykoY29uc3QgVCksIFQgc3RhcnQgPSB7fT4Kc3RydWN0IG1hbmFnZWRfZW51bQp7CgllbnVtCgl7CgkJYSA9IHN0YXJ0LAoJCWIgPSBJTkMoYSksCgkJYyA9IElOQyhiKSwKCX07Cn07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwgVCgqSU5DKShjb25zdCBUKSwgVCBzdGFydCA9IHt9PgpzdHJ1Y3QgbWFuYWdlZF9zdHJvbmdfZW51bQp7CgllbnVtIGNsYXNzIHZhbHVlIDogVAoJewoJCWEgPSBzdGFydCwKCQliID0gSU5DKGEpLAoJCWMgPSBJTkMoYiksCgl9Owp9OwoKaW50IG1haW4oKQp7Cgl1c2luZyBzaGlmdGVkICAgPSBtYW5hZ2VkX2VudW08aW50LCBzaGlmdF9sZWZ0PGludD4sIDE+OwoJdXNpbmcgaW5jcmVtZW50ID0gbWFuYWdlZF9lbnVtPGludCwgaW5jcmVtZW50PGludD4+OwoJdXNpbmcgYmljcmVtZW50ID0gbWFuYWdlZF9lbnVtPGludCwgYmljcmVtZW50PGludD4+OwoKCXVzaW5nIHRlc3QgPSBtYW5hZ2VkX3N0cm9uZ19lbnVtPGludCwgdGVzdDxpbnQ+LCA1PjsKCglzdGQ6OmNvdXQgPDwgIls8PCAxXSAtPiBhOiAiIDw8IHNoaWZ0ZWQ6OmEKCQkJCQkgIDw8ICJcdGI6ICIgPDwgc2hpZnRlZDo6YgoJCQkJCSAgPDwgIlx0YzogIiA8PCBzaGlmdGVkOjpjIDw8ICdcbic7CgoJc3RkOjpjb3V0IDw8ICJbICsxIF0gLT4gYTogIiA8PCBpbmNyZW1lbnQ6OmEKCQkJCQkgIDw8ICJcdGI6ICIgPDwgaW5jcmVtZW50OjpiCgkJCQkJICA8PCAiXHRjOiAiIDw8IGluY3JlbWVudDo6YyA8PCAnXG4nOwoKCXN0ZDo6Y291dCA8PCAiWyArMiBdIC0+IGE6ICIgPDwgYmljcmVtZW50OjphCgkJCQkJICA8PCAiXHRiOiAiIDw8IGJpY3JlbWVudDo6YgoJCQkJCSAgPDwgIlx0YzogIiA8PCBiaWNyZW1lbnQ6OmMgPDwgJ1xuJzsKCglzdGQ6OmNvdXQgPDwgIlt0ZXN0XSAtPiBhOiAiIDw8IGludCh0ZXN0Ojp2YWx1ZTo6YSkKCQkJCQkgIDw8ICJcdGI6ICIgPDwgaW50KHRlc3Q6OnZhbHVlOjpiKQoJCQkJCSAgPDwgIlx0YzogIiA8PCBpbnQodGVzdDo6dmFsdWU6OmMpIDw8ICdcbic7CgoJcmV0dXJuIDA7Cn0=