строковые литералы в качестве аргументов шаблона вызывают дублирование и многословие кода

Строка, созданная во время компиляции, используется в качестве массива символов в структуре, и ее максимальный размер определяется этой строкой. Кроме того, эта структура используется в качестве переменной-члена в другой структуре, и в ней есть несколько таких структур строкового буфера, что, в свою очередь, определяет размер ее хранилища.

Использование строк в качестве аргументов шаблона действительно работает, но приводит к многократному повторению кода, распространяющемуся по исходному коду со скоростью лесного пожара. Ситуация становится еще хуже, когда первая структура имеет несколько строк в качестве аргументов шаблона (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"*/}};

0 ответов

Другие вопросы по тегам