строковые литералы в качестве аргументов шаблона вызывают дублирование и многословие кода
Строка, созданная во время компиляции, используется в качестве массива символов в структуре, и ее максимальный размер определяется этой строкой. Кроме того, эта структура используется в качестве переменной-члена в другой структуре, и в ней есть несколько таких структур строкового буфера, что, в свою очередь, определяет размер ее хранилища.
Использование строк в качестве аргументов шаблона действительно работает, но приводит к многократному повторению кода, распространяющемуся по исходному коду со скоростью лесного пожара. Ситуация становится еще хуже, когда первая структура имеет несколько строк в качестве аргументов шаблона (2 или даже 3).
Вот рабочий пример:
#include <cstddef>
static constinit decltype(auto) c = "abc";
//static constinit decltype(auto) c2 = "12";
// size of A is driven by compile-time-created strings
template<typename T, size_t N /*, typename T2, size_t N2*/>
struct A{
char str[N] {};
// char str2[N2] {};
consteval A(const T(&s)[N] /*, const T2(&s2)[N2]*/) {
for(int i = 0; i < N; ++i){
str[i] = s[i];
if(s[i] == 0) // for strings shorter than storage
break;
}
// for(int i = 0; i < N2; ++i){
// str2[i] = s2[i];
// if(s2[i] == 0)
// break;
// }
}
};
// dummy function which's sole purpose is to help with the type deduction
template<typename T, size_t N /*, typename T2, size_t N2*/>
consteval auto f(const T(&s)[N] /*, const T2(&s2)[N2]*/){
return A<T, N /*, T2, N2*/>(s /*, s2*/);
}
// size of B's members and struct's total size are driven by compile-time
// created strings
struct B{
// explicit (manual) error-prone template params
A<char, 4 /*, char, 3*/> xxx{c /*, c2*/};
// use of a dummy function feels very wrong
decltype(f(c /*, c2*/)) yyy{c /*, c2*/};
// also uses dummy function
decltype(f("abc" /*, "12"*/)) zzz{"abc" /*, "12"*/};
// would like to be able to use shorter strings
//A<char, 4 /*, char, 3*/> fail{"a" /*, "1"*/};
};
3 рабочих примера использования либо подвержены ошибкам, либо приводят к слишком большому повторению кода. И последний, который не работает, является приятной вещью вроде «Интересно, выполнимо ли это?» мне.
Ссылка на проводник компилятора
Есть ли что-то, чего мне не хватает в стандарте C++, что позволило бы мне избежать повторения, сохранив эту автоматизацию, чтобы избежать возможных ошибок вручную?
В идеале я хотел бы просто написать код, подобный приведенному ниже фрагменту:
struct B{
// automatic type deduction without some dummy function's help
A xxx{c /*, c2*/};
// strings in multiple TUs produce independent templates in current standard :(
A<"abc" /*, c2*/> xxx;
};
// usage
// constructs with { {c /*, c2*/}, {"abc" /*, c2*/} }
constinit B b;
// constructs with { {c /*, c2*/}, {"bc" /*, "0"*/} }
constinit B b2{{}, {"bc" /*, "0"*/}};