Stringify числовой аргумент шаблона

#c #templates #stringification

#c #шаблоны #stringification

Вопрос:

У меня есть следующий фрагмент кода:

 template<int maxRegNum> void f(MuliInstr instr);
template<> void f<0>(MuliInstr instr)
{
    if (instr.regA == 0) asm volatile ("mov r4, r0");
}

template<int maxRegNum> void f(MuliInstr instr)
{
    if (instr.regA == maxRegNum) asm volatile ("mov r4, r" ???);
    f<maxRegNum - 1>(instr);
}
 

Что ??? является ли держатель места в коде, где я хочу stringify maxRegNum, возможно ли это каким-то образом с помощью C 11? Решение C-Preprocessor тоже было бы хорошо 🙂

Я хочу добиться того, чтобы использовать это в качестве генератора кода, избегая повторять запись этой инструкции перемещения ассемблера 30 раз, если мне нужно сделать выбор из 30 регистров, например

Спасибо за любой намек на этот вопрос.

С уважением, Стив

РЕДАКТИРОВАТЬ: я хочу добиться следующего:

Когда я пишу f<31>(instr); где-то в коде мне нужны строки

 if (instr.regA == 31) asm volatile ("mov r4, r31");
if (instr.regA == 30) asm volatile ("mov r4, r30");
if (instr.regA == 29) asm volatile ("mov r4, r29");
...
if (instr.regA == 0) asm volatile ("mov r4, r0");
 

помещается в результат компиляции

Комментарии:

1. Вы имеете в виду, что вам нужно значение maxRegNum в строке? Тогда как насчет std::to_string ?

2. Препроцессор не может создать экземпляр аргументов шаблона. Чего именно вы хотите достичь? Для меня это звучит как проблема XY.

3. @Какой-то программист, чувак, Привет, std::to_string не является решением, потому что оно динамическое, инструкция asm должна быть четко определена перед запуском ассемблера.

4. Препроцессор представляет собой простую машину подстановки текста. Он совершенно не знает, с каким языком программирования, если таковой имеется, он работает.

Ответ №1:

К сожалению, вам, вероятно, потребуется указать строковый литерал asm , который вы не можете создать с помощью шаблонов.

Вы можете использовать BOOST_PP_REPEAT_FROM_TO , чтобы сделать это легко с помощью макросов, хотя:

 #include <boost/preprocessor/repetition/repeat_from_to.hpp>

#define F_DEFINITION(_, maxRegNum, __)                                   
template<> void f<maxRegNum>(MuliInstr instr) {                          
    if (instr.regA == maxRegNum) asm volatile ("mov r4, r" #maxRegNum);  
    f<maxRegNum - 1>(instr);                                             
}


BOOST_PP_REPEAT_FROM_TO(1, 30, F_DEFINITION, _)
 

Без boost вы все равно можете избежать некоторых повторений с помощью макросов. Это должен быть эквивалентный код, если ваш regA является целочисленным членом:

 template<int maxRegNum> void f(MuliInstr instr) {
    static_assert(maxRegNum <= 31, "maxRegNum > 31 not supported");
    switch (instr.regA) {
#define F_CASE(n) 
        case n: 
            if (maxRegNum >= n) asm volatile ( "mov r4, r" #n ); 
            break
#define F_CASE_8(a, b, c, d, e, f, g, h) F_CASE(a); F_CASE(b); F_CASE(c); F_CASE(d); F_CASE(e); F_CASE(f); F_CASE(g); F_CASE(h)
        F_CASE_8(0, 1, 2, 3, 4, 5, 6, 7);
        F_CASE_8(8, 9, 10, 11, 12, 13, 14, 15);
        F_CASE_8(16, 17, 18, 19, 20, 21, 22, 23);
        F_CASE_8(24, 25, 26, 27, 28, 29, 30, 31);
    }
}
 

Комментарии:

1. Привет, Артьер, спасибо за этот ответ. Да, вы понимаете, куда я хочу перейти 🙂 Но жаль, что я не могу разрешить его с помощью шаблонов. Я также изо всех сил пытался прийти к результату, но потерпел неудачу 🙂 Хорошо, это решение boost звучит интересно, к сожалению, в моем распоряжении нет boost, поэтому, боюсь, у меня нет альтернативы, кроме написания тонны повторяющегося кода 🙁 В любом случае, большое спасибо за ваш ответ.

2. Основываясь на вашем втором предложении, я реализовал чистое решение для макросов, где, по крайней мере, я могу написать if … (или регистр …), но для удобства чтения я изменил F_CASE_8 в основном на F_CASE_1 и теперь работает с чистой строкой C-preproc. Спасибо за ваши предложения и время. Стив