c++ - reducing syntax "noise" without using a macro -


i'm trying find way of reducing bit of syntax "noise" without resorting macro. following code:

struct base { base() = delete; };     struct tag1 final : private base {     static constexpr const char* name = "tag1"; }; template <typename t> std::string name() { return t::name; } // ... int main() {    const std::string name1(name<tag1>());    return 0; } 

it nice rid of of static constexpr const char* (not mention other) syntax gets annoying repeat tag2, tag3, etc. plus, part of of interesting tag1, rest "noise". straight-forward solution is use macro:

#define make_tag(tag_name) struct tag_name final : private base { \     static constexpr const char* name = #tag_name; }     make_tag(tag2); // ... const std::string name2(name<tag2>()); 

the macro-based make_tag(tag2); syntax has removed of "noise" leaving tag2 quite prominent. added benefit of macro tag_name can turned string literal prevents copy-paste errors.

an "obvious" possible solution might pass name template argument

template<const char* name> base { ... }; struct tag3 final : private base<"tag3"> {}; 

but that's not supported c++. clever work-around, answer below, use variadic template:

template<char... s> struct base { base() = delete;     static std::string name() { return{ s... }; } };     struct tag4 final : base<'t', 'a', 'g', '4'> { }; template <typename t> std::string name() { return t::name(); } 

this reduce of noise, requires writing 't', 'a', 'g', '4' instead of "tag4". run-time solution succinct

struct base {     const std::string name;     base(const std::string& name) : name(name) {} };     struct tag5 final : base { tag5() : base("tag5") {} }; template <typename t> std::string name() { return t().name; } 

but that's not entirely satisfying tag5 can instantiated, ideally doesn't make sense. also, it's necessary write tag5 3 times, isn't dry.

is there way further simplify (i.e., less typing) code above? ... without using macro?

if you're willing type out characters individually, can following:

template<char... s> struct base {      base() = delete;     static std::string name(){         return {s...};     } };  struct tag1 final : private base<'t','a','g','1'> {using base::name;}; struct tag2 final : private base<'t','a','g','2'> {using base::name;}; 

demo

call so:

std::cout << tag1::name() << std::endl; std::cout << tag2::name() << std::endl; 

i had add using base::name in derived classes because you're using private inheritance. if inheritance becomes protected or public, don't need that.

the gist of name() function in base create character array can construct string from. use variadic parameter pack expansion create array.


Comments

Popular posts from this blog

php - Permission denied. Laravel linux server -

google bigquery - Delta between query execution time and Java query call to finish -

python - Pandas two dataframes multiplication? -