Как избежать предупреждения: операция с 'count' может быть неопределенной [-Wsequence-point] - PullRequest
0 голосов
/ 25 мая 2018

Я работаю с N-API Node.js и создаю небольшую оболочку, которая упростит экспорт функций C ++.

template<class T, class... Targs> napi_value Api::create(const char* name, T (* const cb)(Targs...))
{
    // creates JavaScript function that will call cbProxy<> when called
    return create(name, cbProxy<T, Targs...>, cb);
}

template<class T, class... Targs> napi_value Api::cbProxy(const napi_env env, const napi_callback_info info)
{
    // number of arguments
    size_t count = sizeof...(Targs);
    ApiValue args[count];
    T (* cb)(Targs...);
    // retrieve arguments and callback
    if (!Api::getParams(env, info, args, count, &cb))
        return nullptr;

    T ret = cb(Api::getValue<Targs>(&args[--count])...);    
    return Api(env).create(ret);
}

template<> bool Api::getValue(ApiValue* value)
{
    return value->toBool();
}

template<> double Api::getValue(ApiValue* value)
{
    return value->toDouble();
}

template<> int32_t Api::getValue(ApiValue* value)
{
    return value->toInt32();
}

Идея состоит в том, чтобы вызвать api.create("TestFunction", testFn);, который будетвозвращает функцию JS.
Когда она вызывается, она вызывает Api::cbProxy<>, которая преобразует параметры JS в эквивалентные типы C ++ с Api::getValue<T>() и вызывает testFn (cb).

Позволяет сказать testFn имеет следующую подпись: int testFn(bool bVal, double dVal)
Строка T ret = cb(Api::getValue<Targs>(&args[--count])...); расширится до

int ret = cb(Api::getValue<bool>(&args[--count]), 
             Api::getValue<double>(&args[--count]));

, которая работает на 100% нормально, но вызывает предупреждение компилятора.Я немного новичок в отношении C ++, поэтому я ищу лучший способ написать это.

В основном я хочу просмотреть массив args и список параметров типа Targs водин раз.

Просто для пояснения: --count в вызове расширенной функции вызывает следующее предупреждение:
warning: operation on ‘count’ may be undefined [-Wsequence-point]

1 Ответ

0 голосов
/ 25 мая 2018

Полагаю, проблема в том, что в

int ret = cb(Api::getValue<bool>(&args[--count]), 
             Api::getValue<double>(&args[--count]));

порядок вычисления аргумента аргумента зависит от реализации неопределенное поведение (MM-коррекция), поэтому, учитывая count, начиная с2, может быть

int ret = cb(Api::getValue<bool>(&args[1]), 
             Api::getValue<double>(&args[0]));

или

int ret = cb(Api::getValue<bool>(&args[0]), 
             Api::getValue<double>(&args[1]));

Чтобы быть уверенным, что первый индекс args (bool one) равен 1 и чтовторой (double один) - 0, возможный способ - использовать переменные индексы.

Если вы можете использовать C ++ 14, используя метод cbProxyHelper(), вы можете попробовать сделать следующее: (Внимание: код не проверен)

template <typename T, typename ... Targs, std::size_t ... Is>
napi_value Api::cbProxyHelper (const napi_env env,
                               const napi_callback_info info,
                               std::index_sequence<Is...> const &)
 {
   // number of arguments
   constexpr std::size_t count = sizeof...(Targs);
   ApiValue args[count];
   T (* cb)(Targs...);
   // retrieve arguments and callback
   if (!Api::getParams(env, info, args, count, &cb))
      return nullptr;

   T ret = cb(Api::getValue<Targs>(&args[count-1U-Is])...);    
   return Api(env).create(ret);
 }

template <typename T, typename ... Targs>
napi_value Api::cbProxy (const napi_env env, const napi_callback_info info)
 { return cbProxyHelper(env, info, std::index_sequence_for<Targs...>{}); }

Если вы используете C++ 11, имитировать std::index_sequence и std::make_index_sequence не очень сложно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...