#include <cstdio>
namespace intern {
template<char... NN> struct string {
static constexpr char const value[ sizeof...(NN) ]{NN...};
static_assert( value[ sizeof...(NN) - 1 ] == '\0', "interned string was too long" );
static constexpr auto data() { return value; }
};
template<char... N> constexpr char const string<N...>::value[];
template<int N>
constexpr char ch ( char const(&s)[N], int i ) { return i < N ? s[i] : '\0'; }
template<typename T> struct is_string {
static const bool value = false;
};
template<char... NN> struct is_string< string<NN...> > {
static const bool value = true;
};
}
//prefixing macros with a $ helps with readability
#define $c(a,b) intern::ch(a, b)
//10 characters + '\0', add $c(...) for more
#define $(s) intern::string<$c(s,0),$c(s,1),$c(s,2),$c(s,3),$c(s,4),$c(s,5),$c(s,6),$c(s,7),$c(s,8),$c(s,9),$c(s,10)>
struct singleton {
template<typename T>
singleton(T) : name{ T::value } {
if( T::value == $("db")::value )
printf("Initializing DB singleton: %s\n", T::value);
else
printf("Initializing unknown singleton: %s\n", T::value);
}
void do_action() {
printf("singleton(%s)::do_action()\n", name);
}
char const *name;
};
template<typename K, typename V> struct map {
static V value;
};
template<typename K, typename V> V map<K,V>::value{K{}};
template<typename K> using get_singleton = map<K,singleton>;
int main() {
get_singleton< $("db") >::value.do_action();
get_singleton< $("map") >::value.do_action();
}
I2luY2x1ZGUgPGNzdGRpbz4KIApuYW1lc3BhY2UgaW50ZXJuIHsKCiAgdGVtcGxhdGU8Y2hhci4uLiBOTj4gc3RydWN0IHN0cmluZyB7CgogICAgc3RhdGljIGNvbnN0ZXhwciBjaGFyIGNvbnN0IHZhbHVlWyBzaXplb2YuLi4oTk4pIF17Tk4uLi59OwoKICAgIHN0YXRpY19hc3NlcnQoIHZhbHVlWyBzaXplb2YuLi4oTk4pIC0gMSBdID09ICdcMCcsICJpbnRlcm5lZCBzdHJpbmcgd2FzIHRvbyBsb25nIiApOwoKICAgIHN0YXRpYyBjb25zdGV4cHIgYXV0byBkYXRhKCkgeyByZXR1cm4gdmFsdWU7IH0KICB9OwoKICB0ZW1wbGF0ZTxjaGFyLi4uIE4+IGNvbnN0ZXhwciBjaGFyIGNvbnN0IHN0cmluZzxOLi4uPjo6dmFsdWVbXTsKIAogIHRlbXBsYXRlPGludCBOPgogIGNvbnN0ZXhwciBjaGFyIGNoICggY2hhciBjb25zdCgmcylbTl0sIGludCBpICkgeyByZXR1cm4gaSA8IE4gPyBzW2ldIDogJ1wwJzsgfQoKICB0ZW1wbGF0ZTx0eXBlbmFtZSBUPiBzdHJ1Y3QgaXNfc3RyaW5nIHsKICAgIHN0YXRpYyBjb25zdCBib29sIHZhbHVlID0gZmFsc2U7CiAgfTsKCiAgdGVtcGxhdGU8Y2hhci4uLiBOTj4gc3RydWN0IGlzX3N0cmluZzwgc3RyaW5nPE5OLi4uPiA+IHsKICAgIHN0YXRpYyBjb25zdCBib29sIHZhbHVlID0gdHJ1ZTsKICB9Owp9CgovL3ByZWZpeGluZyBtYWNyb3Mgd2l0aCBhICQgaGVscHMgd2l0aCByZWFkYWJpbGl0eQojZGVmaW5lICRjKGEsYikgaW50ZXJuOjpjaChhLCBiKQoKLy8xMCBjaGFyYWN0ZXJzICsgJ1wwJywgYWRkICRjKC4uLikgZm9yIG1vcmUKI2RlZmluZSAkKHMpIGludGVybjo6c3RyaW5nPCRjKHMsMCksJGMocywxKSwkYyhzLDIpLCRjKHMsMyksJGMocyw0KSwkYyhzLDUpLCRjKHMsNiksJGMocyw3KSwkYyhzLDgpLCRjKHMsOSksJGMocywxMCk+CgpzdHJ1Y3Qgc2luZ2xldG9uIHsKCQoJdGVtcGxhdGU8dHlwZW5hbWUgVD4KCXNpbmdsZXRvbihUKSA6IG5hbWV7IFQ6OnZhbHVlIH0gewoJCWlmKCBUOjp2YWx1ZSA9PSAkKCJkYiIpOjp2YWx1ZSApCgkJCXByaW50ZigiSW5pdGlhbGl6aW5nIERCIHNpbmdsZXRvbjogJXNcbiIsIFQ6OnZhbHVlKTsKCQllbHNlIAoJCQlwcmludGYoIkluaXRpYWxpemluZyB1bmtub3duIHNpbmdsZXRvbjogJXNcbiIsIFQ6OnZhbHVlKTsKCX0KCQoJdm9pZCBkb19hY3Rpb24oKSB7CgkJcHJpbnRmKCJzaW5nbGV0b24oJXMpOjpkb19hY3Rpb24oKVxuIiwgbmFtZSk7Cgl9CgoJY2hhciBjb25zdCAqbmFtZTsKfTsKCnRlbXBsYXRlPHR5cGVuYW1lIEssIHR5cGVuYW1lIFY+IHN0cnVjdCBtYXAgewogIHN0YXRpYyBWIHZhbHVlOwp9OwoKdGVtcGxhdGU8dHlwZW5hbWUgSywgdHlwZW5hbWUgVj4gViBtYXA8SyxWPjo6dmFsdWV7S3t9fTsKCnRlbXBsYXRlPHR5cGVuYW1lIEs+IHVzaW5nIGdldF9zaW5nbGV0b24gPSBtYXA8SyxzaW5nbGV0b24+OwoKaW50IG1haW4oKSB7CiAKCWdldF9zaW5nbGV0b248ICQoImRiIikgPjo6dmFsdWUuZG9fYWN0aW9uKCk7CglnZXRfc2luZ2xldG9uPCAkKCJtYXAiKSA+Ojp2YWx1ZS5kb19hY3Rpb24oKTsKCn0K