It can be done in C++17 but you need static constexpr
storage for the C string before you pass it as name: https://godbolt.org/z/ojnv8xPca
#include<cstddef>
#include<string> //std::size()
namespace util {
template<std::size_t N>
using c_str = char const [N];
template<auto const & str, std::size_t iter = std::size(str), char const ... chars>
struct c_str_to_arg_pack {
using arg_pack_t =
typename c_str_to_arg_pack<str, iter-1, str[iter-1], chars ... >
::arg_pack_t;
};
template<auto const & str, char const ... chars>
struct c_str_to_arg_pack<str, 0, chars ...> {
using arg_pack_t = c_str_to_arg_pack<str, 0, chars...>;
template <template <char ...> typename T>
using apply = T<chars ...>;
};
template<auto const & str, char const ... chars>
using c_str_to_arg_pack_t = typename c_str_to_arg_pack<str, chars ... >::arg_pack_t;
}//end util
#include<string_view>
#include<array>
template <char ... chars>
struct module_base {
std::string const & get_name() {
static std::string name = []()
{
std::string name;
name.reserve(sizeof...(chars));
(name += ... += chars);
return name;
}();
return name;
};
static constexpr std::array<char, sizeof ... (chars)> name_backing {chars ...};
static constexpr std::string_view constexpr_name {name_backing.begin(), name_backing.size() };
static int instance_count;
module_base (){
++instance_count;
}
virtual ~module_base() = default;
};
template <char ... chars>
int module_base<chars ...>::instance_count {};
template <auto const & name>
struct xyz : util::c_str_to_arg_pack_t<name>::template apply<module_base> //edit, formerly missing 'template'
{};
template <auto const & name>
struct abc : util::c_str_to_arg_pack_t<name>::template apply<module_base> //edit, formerly missing 'template'
{};
#include<iostream>
int main(){
static constexpr util::c_str<std::size("beans\n")> beans {"beans\n"};
xyz<beans> test{};
std::cout << test.get_name();
static constexpr util::c_str<std::size("beans\n")> beans_two {"beans\n"};
abc<beans_two> test_two{};
std::cout << test_two.constexpr_name;
std::cout << decltype(test)::instance_count << '\n';
std::cout << decltype(test_two)::instance_count << '\n';
}