Могу ли я перейти на тип аргумента в пакет параметров в C ++ 17? - PullRequest
1 голос
/ 29 февраля 2020

Текущая (старая) сигнатура вызова функции:

        long vmcall(const std::string& function_name,
                    std::vector<address_t> args);

Теперь, поскольку я могу звонить только гостю, используя целые (размер адреса), это довольно ограниченный интерфейс, и я хочу его расширить по крайней мере, также обрабатывать значения с плавающей запятой и, возможно, другие, например, так:

        template <typename... Args>
        long vmcall(const std::string& function_name,
                    Args&&... args);

Это будет новая сигнатура функции, заменяющая старую.

Чтобы показать, как вектор аргументов в настоящее время используется:

template <int W>
inline void Machine<W>::setup_call(
        address_t call_addr, address_t retn_addr,
        std::vector<address_t> args)
{
    assert(args.size() <= 8);
    cpu.reg(RISCV::REG_RA) = retn_addr;
    for (size_t arg = 0; arg < args.size(); arg++) {
        cpu.reg(RISCV::REG_ARG0 + arg) = args[arg];
    }
    cpu.jump(call_addr);
}

Эта функция вызывается из vmcall с помощью std :: move (args), и все, что она делает, это копирует целочисленные аргументы в векторе args в интегральные регистры ЦП, постепенно. Это прекрасно работает, когда я хочу вызвать функцию, которая принимает только интегральные аргументы. Итак, если бы я хотел вызвать функцию, которая, скажем, принимает один аргумент с плавающей точкой, то сделать это невозможно. Это связано с тем, что регистры FP полностью разделены и должны обрабатываться по-разному.

Кроме того, 32-разрядные и 64-разрядные операции с плавающей запятой обрабатываются по-разному посредством NaN-бокса. Итак, было бы неплохо, если бы можно было различить и float, и double.

Я не так силен в магах шаблонов c для начала. Как мне перейти на тип каждого элемента в пакете параметров?

1 Ответ

4 голосов
/ 29 февраля 2020

В C ++ 17 способ перебора пакета параметров заключается в использовании запятой fold :

(<expr>, ...); // expr contains Args and/or args

Если одного выражения недостаточно, вы можете использовать Вызванная немедленно лямбда:

([&] {
    <statements> // statements contains Args and/or args
 }(), ...);

Объедините это с if constexpr для типов ваших аргументов:

std::vector<address_t> addr_args;
std::vector<fp_t> fp_args;
([&] {
    if constexpr (std::is_integral_v<Args>)
        addr_args.push_back(args);
    else
        fp_args.push_back(args);
 }(), ...);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...