Пытаюсь вычесть std ::chrono::duration из time_point (C ), но мой код не компилируется. Есть какие-нибудь предложения?

#c #time #duration #chrono

#c #время #Продолжительность #chrono

Вопрос:

Я задал этот вопрос вчера, но мой поток был закрыт, поэтому я говорю в пустоту. Итак, мой код не компилируется, но я бы очень этого хотел. Вот мой фрагмент:

 float numSeconds = 50;
std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::now();
auto duration = std::chrono::duration<float, std::chrono::seconds>(numSeconds);
startTime -= duration;
 

Похоже, это должно быть довольно просто, но я получаю ошибку operator not found при попытке вычитания на месте. Есть предложения? Я также попытался заменить третью строку следующим:

    auto duration = std::chrono::duration<float, std::ratio<1, 1>>(numSeconds);
 

Однако эта строка, похоже, не является причиной проблем, оба подхода кажутся допустимыми. Это моя последняя строка, которая все еще недовольна. Код ошибки, который я получаю, это:

 "Error  C2679   binary '-=': no operator found which takes a right-hand operand of type 'std::chrono::duration<float,std::chrono::seconds>' (or there is no acceptable conversion)"
 

Кроме того, когда я меняю последнюю строку на:

 timer.m_startTime = timer.m_startTime - duration;
 

Я получаю следующий код ошибки:

 Error   C2679   binary '=': no operator found which takes a right-hand operand of type 'std::chrono::time_point<std::chrono::steady_clock,std::chrono::duration<float,std::ratio<1,1000000000>>>' (or there is no acceptable conversion)
 

Это как-то несовместимые типы? Я бы подумал, что они разрешат одно и то же.

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

1. Не знаю всех подробностей. Указанная вами продолжительность, похоже, имеет другой тип, чем значение по умолчанию для steady clock . Должен быть тип std::chrono::steady_clock::duration .

2. Так кажется! Однако, std::chrono::steady_clock::duration<float, std::ratio<1, 1>> похоже, это не правильный способ инициализации длительности, поэтому я не уверен, как получить правильный тип длительности из числа секунд с плавающей запятой.

3. Я думаю, проблема в том, что вы пытаетесь установить / изменить аргументы шаблона, что приводит к несовместимому типу. Но в любом случае, в настоящее время я не могу вам помочь.

4. Возможно, я думаю, что мне просто понадобилось явное приведение. Попытка auto duration = std::chrono::duration_cast<std::chrono::steady_clock::duration>( std::chrono::duration<float, std::ratio<1, 1>>(seconds)); может быть ошибкой, поскольку она компилируется. Я добавлю это в качестве ответа, если он действительно поступает правильно.

Ответ №1:

 float numSeconds = 50;
 

Следующая строка:

 std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::now();
 

можно было бы более кратко записать как:

 auto startTime = std::chrono::steady_clock::now();
 

Оба синтаксиса эквивалентны и верны.

Причина, по которой это не компилируется:

 auto duration = std::chrono::duration<float, std::chrono::seconds>(numSeconds);
 

заключается в том, что второй аргумент шаблона duration принимает a std::ratio , а не a std::chrono::duration . Правильный способ сказать это:

 auto duration = std::chrono::duration<float, std::ratio<1, 1>>(numSeconds);
 

Вышеуказанное означает, что duration тип std::chrono::duration имеет представление float и период в 1/1 секунды. Это означает, что это всего лишь количество секунд с плавающей запятой.

Второй параметр шаблона std::ratio по умолчанию равен 1, поэтому приведенное выше можно упростить до:

 auto duration = std::chrono::duration<float, std::ratio<1>>(numSeconds);
 

И второй параметр шаблона std::chrono::duration по умолчанию std::ratio<1> имеет значение, поэтому вышесказанное можно упростить до:

 auto duration = std::chrono::duration<float>(numSeconds);
 

Следующее не компилируется:

 startTime -= duration;
 

потому chrono что есть правило, согласно которому значения с представлением с плавающей запятой никогда не преобразуются неявно в значения с целочисленным представлением. Это делается для того, чтобы избежать ошибки усечения, возникающей при присвоении a float значению an int .

Есть несколько способов исправить это. Например, вы могли бы сохранить результат в a float -based time_point :

 auto anotherTime = startTime - duration;
 

anotherTime имеет тип std::chrono::time_point<std::chrono::steady_clock, std::chrono::duration<float, std::chrono::steady_clock::period>> .

Или вы можете явно привести duration обратно к целочисленному типу:

 startTime -= std::chrono::duration_cast<std::chrono::seconds>(duration);
 

Если вы выберете последнее, тогда вообще нет смысла использовать float . И вся последовательность может выглядеть так:

 using namespace std::chrono_literals;
auto startTime = std::chrono::steady_clock::now();
auto duration = 50s;
startTime -= duration;
 

или:

 using namespace std::chrono_literals;
auto startTime = std::chrono::steady_clock::now();
startTime -= 50s;
 

или:

 using namespace std::chrono_literals;
auto startTime = std::chrono::steady_clock::now() - 50s;
 

Вот 1-часовой видеоурок <chrono> , который может оказаться полезным для вас: https://www.youtube.com/watch?v=P32hvk8b13M

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

1. Спасибо, Говард, это невероятно тщательно! Я думаю, что about охватывает все вопросы, которые у меня могли возникнуть.