Visual принимает std :: string из итератора std :: byte - PullRequest
0 голосов
/ 28 августа 2018

Этот код прекрасно компилируется в Visual и не работает в GCC или Clang.

Я понимаю, что преобразование из std::byte в char может быть проблемой. Запрещено ли предоставлять это преобразование, и это визуальная ошибка в C ++, или это приемлемо, а в GCC / Clang отсутствует полезная функция?

#include <vector>
#include <string>

int main()
{
    std::vector<std::byte> test(10);
    std::string str(test.begin(), test.end());
}

Редактировать

Microsoft (исправил это)

Мы исправили проблему в следующем выпуске. Теперь MSVC предоставляют ошибка как ниже: ошибка C2664: 'void станд :: basic_string, станд :: Распределитель> :: push_back (Const _Elem) ': невозможно преобразовать аргумент 1 из' std :: byte 'в' const _Elem 'с помощью [ _Elem = char]

Ответы [ 2 ]

0 голосов
/ 28 августа 2018

Конструктор строки MSVS, который принимает пару итераторов, выглядит как

template<class _Iter,
    class = enable_if_t<_Is_iterator_v<_Iter>>>
    basic_string(_Iter _First, _Iter _Last, const _Alloc& _Al = _Alloc())
    : _Mybase(_Al)
    {   // construct from [_First, _Last) with optional allocator
    _Tidy_init();
    _Adl_verify_range(_First, _Last);
    _Construct(_Get_unwrapped(_First), _Get_unwrapped(_Last), _Iter_cat_t<_Iter>());
    }

и _Construct возможные звонки

template<class _Iter>
    void _Construct(_Iter _First, const _Iter _Last, input_iterator_tag)
    {   // initialize from [_First, _Last), input iterators
    _TRY_BEGIN
    for (; _First != _Last; ++_First)
        {
        push_back(static_cast<_Elem>(*_First));
        }

    _CATCH_ALL
    _Tidy_deallocate();
    _RERAISE;
    _CATCH_END
    }

Важным битом является push_back(static_cast<_Elem>(*_First));. Обычно вы не сможете назначить std::byte напрямую другому типу, поскольку это перечисление с ограничением, но, поскольку есть static_cast, вы можете обойти это. Вот почему вы можете использовать диапазон байтов для инициализации std::string.

При этом конструктор итератора требует от [sequence.reqmts] - Таблица 68 , что

T должен быть EmplaceConstructible в X с *i.

и [container.requirements.general] /15.5 утверждает, что EmplaceConstructible означает

T является EmplaceConstructible в X из args, для нуля или более аргументов args, означает, что следующее выражение правильно сформировано:

allocator_traits<A>::construct(m, p, args)

и construct определены в [allocator.requirements] - Таблица 33 как

Эффекты: Создает объект типа C в c

По умолчанию ::new ((void*)c)C(forward<Args>(args)...)

Так что до сих пор неясно, разрешено это или нет.

0 голосов
/ 28 августа 2018

Visual C ++ не так. std::byte - это перечисление в области видимости, , т. Е. , объявленное как бы enum class, и поэтому не может быть преобразовано в char или любой другой арифметический тип, если не используется явное приведение.

...