VC++ 11 - std::condition_variable_any не совместим со стандартом?

Недавно я столкнулся со странными проблемами компиляции в Microsoft Visual Studio 2012 (оснащенной Visual C++ 11).

Я перенес большую базу кода, разработанную в основном на Linux, с учетом широкого использования C++ 11. Несмотря на несколько небольших изменений, все работало нормально. За исключением одного: я получил странную ошибку о типе результата std:: condition_variable:: wait_for. Его содержание здесь неактуально, потому что я проверил это и...

Справочная страница (ссылка выше) гласит:

template< class Lock, class Rep, class Period >
std::cv_status wait_for(Lock&, const std::chrono::duration<Rep, Period>&)

А также:

template< class Lock, class Rep, class Period, class Predicate >
bool wait_for(Lock&, const std::chrono::duration<Rep, Period>&, Predicate)

я использовал std::cv_status в некоторых местах, так что я могу сказать, я полагаюсь на его присутствие. Тем не менее, на MSVC11, <conditional_variable> содержит:

template<class _Lock, class _Rep, class _Period>
bool wait_for(_Lock& _Lck, const chrono::duration<_Rep, _Period>& _Rel_time)

А также:

template<class _Lock, class _Rep, class _Period, class _Predicate>
bool wait_for(_Lock& _Lck, const chrono::duration<_Rep, _Period>& _Rel_time, _Predicate _Pred)

Обратите внимание на другой тип результата в первом случае. Я был как:

Ээээ... что?

Я сразу же проверил это на Linux (g++ 4.8) и эти два метода действительно были определены правильно.

Что тут происходит? MS выпустила реализацию, не совместимую со стандартом?

Любопытно, что я дополнительно исследовал <condition_variable> и я нашел это:

namespace cv_status {   // names for wait returns
    enum cv_status {
        timeout,
        no_timeout
    };
} // namespace cv_status

Но это:

  • неиспользуемый
  • неверно (*)

Это какая-то известная ошибка? Или, возможно, стандарт позволяет реализации сделать это?


(*) Стандарт определяет enum class cv_status не enum class cv_status::cv_status,


Еще кое-что: wait_for звонки внутри wait_until, который выглядит так:

bool _Res;
_Mtx_lock(&_Mtx);
_Xtrnl.unlock();
_Res = _Cnd_timedwaitX(&_Cnd, &_Mtx, _Abs_time) != _Thrd_timedout;
_Mtx_unlock(&_Mtx);
_Xtrnl.lock();
return (_Res);

Итак, интерпретация результата такова:

  • true -> std::cv_status::no_timeout
  • false -> std::cv_status::timeout

Если было требование, то no_timeout должен быть определен как 1 а также timeout как 0 было бы хорошо, но я не вижу ничего подобного. На самом деле в Linux было:

enum class cv_status { no_timeout, timeout };

Таким образом, эти перечислители будут преобразованы в bool иначе, чем в Windows.

1 ответ

Решение

Несмотря на номер версии Visual C++ 11.0, Visual Studio 2012 не поддерживает C++ 11 и не претендует на его поддержку. Даже в следующей версии (Visual Studio 2013) нет: есть CTP для добавления значительных функций C++ 11, но даже тогда поддержка не завершена. Ожидается, что Visual Studio 2015 будет в основном C++ 11 с полной функциональностью и языком, но я не уверен, будет ли реализация стандартной библиотеки такой же.

В то время как C++ 11 был стандартизирован, был момент, когда эта функция была указана для возврата bool, Именно в этот момент Microsoft добавила его в свою реализацию, и, поскольку C++ 11 все равно не поддерживался, он просто не обновлялся, когда обновлялся стандарт.

В комментариях указывается, что эта конкретная функция уже была изменена в VS2013, но, тем не менее, если вы хотите реализацию C++ 11, то ни VS2012, ни VS2013 не подойдут.

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