#include <iostream>
#include <type_traits>
//#define DONT_SUPPORT_DEFAULTS
template < class _B, template < class ,class ,_B> class ... _Fs>
class Flags
{
public :
template < _B... _Vs>
class WithValues : public _Fs< _B, Flags< _B,_Fs...> :: WithValues < _Vs...> , _Vs> ...
{
public :
typedef _B base_type;
template < base_type _V>
inline constexpr explicit WithValues( std:: integral_constant < base_type, _V> ) : x( _V) { } // done in a strange way to allow the more natural constructor be non-constexpr
inline explicit WithValues( base_type b) : x( b) { } // non-constexpr so I can add an exception to the body
// ... (implementation details unnecessary)
private : base_type x;
} ;
private :
struct _F { template < _B _V> inline constexpr explicit _F( std:: integral_constant < _B, _V> ) { } } ; // dummy class which can be given to a flag-name template
static constexpr unsigned _count = sizeof ...( _Fs< _B, _F, 1 > ) ; // we count the flags, but only in a dummy way
static inline constexpr _B pow2( unsigned exp , _B base = 2 , _B result = 1 ) { return exp < 1 ? result : pow2( exp / 2 , base* base, ( exp % 2 ) ? result* base : result) ; }
#ifndef DONT_SUPPORT_DEFAULTS
template < _B... _Is> struct indices { using next = indices< _Is..., sizeof ...( _Is) > ; using WithPow2Values = WithValues< pow2( _Is) ...> ; } ;
template < unsigned N> struct build_indices { using type = typename build_indices< N- 1 > :: type :: next ; } ;
template <> struct build_indices< 0 > { using type = indices<> ; } ;
//// Another attempt
//template < _B... _Is> struct indices { using WithPow2Values = WithValues<pow2(_Is)...>; };
//template <unsigned N, _B... _Is> struct build_indices : build_indices<N-1, N-1, _Is...> { };
//template < _B... _Is> struct build_indices<0, _Is...> : indices<_Is...> { };
public :
using WithDefaultValues = typename build_indices< _count> :: type :: WithPow2Values ;
#endif
} ;
template < class _B, class _F, _B _V> struct FLAG_A { static constexpr const _F A = _F( std:: integral_constant < _B,_V> ( ) ) ; } ;
template < class _B, class _F, _B _V> struct FLAG_B { static constexpr const _F B = _F( std:: integral_constant < _B,_V> ( ) ) ; } ;
template < class _B, class _F, _B _V> struct FLAG_C { static constexpr const _F C = _F( std:: integral_constant < _B,_V> ( ) ) ; } ;
typedef Flags< unsigned char , FLAG_A, FLAG_B, FLAG_C> :: WithValues < 1 , 2 , 4 > MyFlags;
#ifndef DONT_SUPPORT_DEFAULTS
typedef Flags< unsigned char , FLAG_A, FLAG_B, FLAG_C> :: WithDefaultValues MyFlags2;
#endif
int main( )
{
std:: cout << "Compiled and ran!" << std:: endl ;
return 0 ;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CgovLyNkZWZpbmUgRE9OVF9TVVBQT1JUX0RFRkFVTFRTCgp0ZW1wbGF0ZTxjbGFzcyBfQiwgdGVtcGxhdGUgPGNsYXNzLGNsYXNzLF9CPiBjbGFzcy4uLiBfRnM+CmNsYXNzIEZsYWdzCnsKcHVibGljOgogICAgdGVtcGxhdGU8X0IuLi4gX1ZzPgogICAgY2xhc3MgV2l0aFZhbHVlcyA6IHB1YmxpYyBfRnM8X0IsIEZsYWdzPF9CLF9Gcy4uLj46OldpdGhWYWx1ZXM8X1ZzLi4uPiwgX1ZzPi4uLgogICAgewogICAgcHVibGljOgogICAgICAgIHR5cGVkZWYgX0IgYmFzZV90eXBlOwogICAgICAgIHRlbXBsYXRlIDxiYXNlX3R5cGUgX1Y+CgkgICAgaW5saW5lIGNvbnN0ZXhwciBleHBsaWNpdCBXaXRoVmFsdWVzKHN0ZDo6aW50ZWdyYWxfY29uc3RhbnQ8YmFzZV90eXBlLCBfVj4pIDogeChfVikgeyB9IC8vIGRvbmUgaW4gYSBzdHJhbmdlIHdheSB0byBhbGxvdyB0aGUgbW9yZSBuYXR1cmFsIGNvbnN0cnVjdG9yIGJlIG5vbi1jb25zdGV4cHIKICAgICAgICBpbmxpbmUgZXhwbGljaXQgV2l0aFZhbHVlcyhiYXNlX3R5cGUgYikgOiB4KGIpIHsgfSAvLyBub24tY29uc3RleHByIHNvIEkgY2FuIGFkZCBhbiBleGNlcHRpb24gdG8gdGhlIGJvZHkKCiAgICAgICAgLy8gLi4uIChpbXBsZW1lbnRhdGlvbiBkZXRhaWxzIHVubmVjZXNzYXJ5KQoKICAgIHByaXZhdGU6IGJhc2VfdHlwZSB4OwogICAgfTsKcHJpdmF0ZToKICAgIHN0cnVjdCBfRiB7IHRlbXBsYXRlIDxfQiBfVj4gaW5saW5lIGNvbnN0ZXhwciBleHBsaWNpdCBfRihzdGQ6OmludGVncmFsX2NvbnN0YW50PF9CLCBfVj4pIHsgfSB9OyAvLyBkdW1teSBjbGFzcyB3aGljaCBjYW4gYmUgZ2l2ZW4gdG8gYSBmbGFnLW5hbWUgdGVtcGxhdGUKICAgIHN0YXRpYyBjb25zdGV4cHIgdW5zaWduZWQgX2NvdW50ID0gc2l6ZW9mLi4uKF9GczxfQiwgX0YsIDE+KTsgLy8gd2UgY291bnQgdGhlIGZsYWdzLCBidXQgb25seSBpbiBhIGR1bW15IHdheQoKICAgIHN0YXRpYyBpbmxpbmUgY29uc3RleHByIF9CIHBvdzIodW5zaWduZWQgZXhwLCBfQiBiYXNlID0gMiwgX0IgcmVzdWx0ID0gMSkgeyByZXR1cm4gZXhwIDwgMSA/IHJlc3VsdCA6IHBvdzIoZXhwLzIsIGJhc2UqYmFzZSwgKGV4cCAlIDIpID8gcmVzdWx0KmJhc2UgOiByZXN1bHQpOyB9CgojaWZuZGVmIERPTlRfU1VQUE9SVF9ERUZBVUxUUwogICAgdGVtcGxhdGUgPF9CLi4uIF9Jcz4gIHN0cnVjdCBpbmRpY2VzICAgICAgICAgIHsgdXNpbmcgbmV4dCA9IGluZGljZXM8X0lzLi4uLCBzaXplb2YuLi4oX0lzKT47IHVzaW5nIFdpdGhQb3cyVmFsdWVzID0gV2l0aFZhbHVlczxwb3cyKF9JcykuLi4+OyB9OwogICAgdGVtcGxhdGUgPHVuc2lnbmVkIE4+IHN0cnVjdCBidWlsZF9pbmRpY2VzICAgIHsgdXNpbmcgdHlwZSA9IHR5cGVuYW1lIGJ1aWxkX2luZGljZXM8Ti0xPjo6dHlwZTo6bmV4dDsgfTsKICAgIHRlbXBsYXRlIDw+ICAgICAgICAgICBzdHJ1Y3QgYnVpbGRfaW5kaWNlczwwPiB7IHVzaW5nIHR5cGUgPSBpbmRpY2VzPD47IH07CgogICAgLy8vLyBBbm90aGVyIGF0dGVtcHQKICAgIC8vdGVtcGxhdGUgPCAgICAgICAgICAgIF9CLi4uIF9Jcz4gc3RydWN0IGluZGljZXMgeyB1c2luZyBXaXRoUG93MlZhbHVlcyA9IFdpdGhWYWx1ZXM8cG93MihfSXMpLi4uPjsgfTsKICAgIC8vdGVtcGxhdGUgPHVuc2lnbmVkIE4sIF9CLi4uIF9Jcz4gc3RydWN0IGJ1aWxkX2luZGljZXMgICAgICAgICAgICA6IGJ1aWxkX2luZGljZXM8Ti0xLCBOLTEsIF9Jcy4uLj4geyB9OwogICAgLy90ZW1wbGF0ZSA8ICAgICAgICAgICAgX0IuLi4gX0lzPiBzdHJ1Y3QgYnVpbGRfaW5kaWNlczwwLCBfSXMuLi4+IDogaW5kaWNlczxfSXMuLi4+ICAgICAgICAgICAgICAgeyB9OwoKcHVibGljOgogICAgdXNpbmcgV2l0aERlZmF1bHRWYWx1ZXMgPSB0eXBlbmFtZSBidWlsZF9pbmRpY2VzPF9jb3VudD46OnR5cGU6OldpdGhQb3cyVmFsdWVzOwojZW5kaWYKfTsKCnRlbXBsYXRlIDxjbGFzcyBfQiwgY2xhc3MgX0YsIF9CIF9WPiBzdHJ1Y3QgRkxBR19BIHsgc3RhdGljIGNvbnN0ZXhwciBjb25zdCBfRiBBID0gX0Yoc3RkOjppbnRlZ3JhbF9jb25zdGFudDxfQixfVj4oKSk7IH07CnRlbXBsYXRlIDxjbGFzcyBfQiwgY2xhc3MgX0YsIF9CIF9WPiBzdHJ1Y3QgRkxBR19CIHsgc3RhdGljIGNvbnN0ZXhwciBjb25zdCBfRiBCID0gX0Yoc3RkOjppbnRlZ3JhbF9jb25zdGFudDxfQixfVj4oKSk7IH07CnRlbXBsYXRlIDxjbGFzcyBfQiwgY2xhc3MgX0YsIF9CIF9WPiBzdHJ1Y3QgRkxBR19DIHsgc3RhdGljIGNvbnN0ZXhwciBjb25zdCBfRiBDID0gX0Yoc3RkOjppbnRlZ3JhbF9jb25zdGFudDxfQixfVj4oKSk7IH07Cgp0eXBlZGVmIEZsYWdzPHVuc2lnbmVkIGNoYXIsIEZMQUdfQSwgRkxBR19CLCBGTEFHX0M+OjpXaXRoVmFsdWVzPDEsIDIsIDQ+IE15RmxhZ3M7CiNpZm5kZWYgRE9OVF9TVVBQT1JUX0RFRkFVTFRTCnR5cGVkZWYgRmxhZ3M8dW5zaWduZWQgY2hhciwgRkxBR19BLCBGTEFHX0IsIEZMQUdfQz46OldpdGhEZWZhdWx0VmFsdWVzIE15RmxhZ3MyOwojZW5kaWYKCmludCBtYWluKCkKewogICAgc3RkOjpjb3V0IDw8ICJDb21waWxlZCBhbmQgcmFuISIgPDwgc3RkOjplbmRsOwoJcmV0dXJuIDA7Cn0=
compilation info
prog.cpp:32:15: error: explicit specialization in non-namespace scope ‘class Flags<_B, _Fs>’
template <> struct build_indices<0> { using type = indices<>; };
^
prog.cpp:32:34: error: template parameters not used in partial specialization:
template <> struct build_indices<0> { using type = indices<>; };
^
prog.cpp:32:34: error: ‘_B’
prog.cpp:32:34: error: ‘template<class, class, _B <anonymous> > class ... _Fs’
prog.cpp:31:105: error: template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum) instantiating ‘struct Flags<unsigned char, FLAG_A, FLAG_B, FLAG_C>::build_indices<4294966400u>’
template <unsigned N> struct build_indices { using type = typename build_indices<N-1>::type::next; };
^
prog.cpp:31:105: recursively required from ‘struct Flags<unsigned char, FLAG_A, FLAG_B, FLAG_C>::build_indices<2u>’
prog.cpp:31:105: required from ‘struct Flags<unsigned char, FLAG_A, FLAG_B, FLAG_C>::build_indices<3u>’
prog.cpp:40:83: required from ‘class Flags<unsigned char, FLAG_A, FLAG_B, FLAG_C>’
prog.cpp:48:53: required from here
prog.cpp:31:105: error: invalid use of incomplete type ‘struct Flags<unsigned char, FLAG_A, FLAG_B, FLAG_C>::build_indices<4294966400u>’
prog.cpp:31:34: error: declaration of ‘struct Flags<unsigned char, FLAG_A, FLAG_B, FLAG_C>::build_indices<4294966400u>’
template <unsigned N> struct build_indices { using type = typename build_indices<N-1>::type::next; };
^
stdout