2

This code compile fine in Visual and failed in GCC or Clang.

I understand that the conversion from std::byte to char might be a problem. Is it forbidden to provide this conversion and is a visual C++ bug or is it acceptable and a nice feature missing from GCC/Clang?

#include <vector>
#include <string>

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

Edit

Microsoft (fixed it)

We have fixed the problem in a future release. Now MSVC provide an error like below: error C2664: 'void std::basic_string,std::allocator>::push_back(const _Elem)': cannot convert argument 1 from 'std::byte' to 'const _Elem' with [ _Elem=char ]

4
  • @Someprogrammerdude I think the concern here is the discrepancy between Visual C++ and GCC and Clang. Commented Aug 28, 2018 at 15:34
  • @Someprogrammerdude std::byte is distinct from the other types you mention in that it's isn't considered a character type and is not considered an integral type. Commented Aug 28, 2018 at 15:36
  • MS fails to compile this code so they must be doing something special to handle std::byte. Commented Aug 28, 2018 at 15:36
  • Are you using the /J (default char type is unsigned) compiler option? If I read this right it would allow this to compile. Commented Aug 28, 2018 at 17:27

2 Answers 2

2

MSVS's string constructor that takes an iterator pair looks like

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>());
    }

And _Construct eventualy calls

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
    }

With the important bit being push_back(static_cast<_Elem>(*_First));. Normally you would not be able to assign a std::byte directly to another type since it is a scoped enumeration but since there is a static_cast you get around that. This is why you are able to use a range of bytes to initialize a std::string.

That said the iterator constructor requires from [sequence.reqmts] - Table 68 that

T shall be EmplaceConstructible into X from *i.

and [container.requirements.general]/15.5 states that EmplaceConstructible means

T is EmplaceConstructible into X from args , for zero or more arguments args, means that the following expression is well-formed:

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

and construct is defined in [allocator.requirements] - Table 33 as

Effects: Constructs an object of type C at c

Default ::new ((void*)c)C(forward<Args>(args)...)

So it is still unclear if this is allowed or not.

Sign up to request clarification or add additional context in comments.

2 Comments

I read this through a second time following through the standard language chain to Effects: Constructs an object of type C at c. After thinking a while I don't see any indication that Constructs an object would leave open a gap for special-case conversions to be added by an implementation, especially corroborated by the fact that the default implementation doesn't allow such things.
char was signed so it looks like a bug to me to convert std::byte to char
1

Visual C++ is wrong. std::byte is a scoped enumeration, i.e., declared as if by enum class, and therefore cannot be converted to char or any other arithmetic type unless an explicit cast is used.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.