【问题标题】:Visual accept std::string from std::byte iterator视觉接受来自 std::byte 迭代器的 std::string
【发布时间】:2019-02-03 07:14:13
【问题描述】:

此代码在 Visual 中编译良好,但在 GCC 或 Clang 中编译失败。

我了解从std::bytechar 的转换可能存在问题。是否禁止提供这种转换并且是一个可视的 C++ 错误,还是可以接受并且 GCC/Clang 缺少一个不错的功能?

#include <vector>
#include <string>

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

编辑

微软(fixed it)

我们在未来的版本中解决了这个问题。现在 MSVC 提供了一个 如下错误:错误C2664:'无效 std::basic_string,std::allocator>::push_back(const _Elem)':无法使用 [ 将参数 1 从 'std::byte' 转换为 'const _Elem' _Elem=char ]

【问题讨论】:

  • @Someprogrammerdude 我认为这里关注的是 Visual C++ 与 GCC 和 Clang 之间的差异。
  • @Someprogrammerdude std::byte 与您提到的其他类型不同,它不被视为字符类型,也不被视为整数类型。
  • MS 无法编译this code,所以他们必须做一些特殊的事情来处理std::byte
  • 您是否使用 /J(默认字符类型为无符号)编译器选项?如果我没看错,它将允许编译。

标签: c++ gcc visual-c++ clang language-lawyer


【解决方案1】:

采用迭代器对的 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&lt;_Elem&gt;(*_First));。通常您无法将std::byte 直接分配给另一种类型,因为它是一个作用域枚举,但由于存在static_cast,您可以绕过它。 这就是为什么您可以使用一系列字节来初始化std::string

也就是说迭代器构造函数需要[sequence.reqmts] - Table 68那个

T 应该是 EmplaceConstructible 到 X*i

[container.requirements.general]/15.5 声明EmplaceConstructible 表示

T is EmplaceConstructible into X from args,对于零个或多个参数args,意味着以下表达式是良构的:

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

construct[allocator.requirements] - Table 33 中定义为

效果:在 c 处构造一个 C 类型的对象

默认::new ((void*)c)C(forward&lt;Args&gt;(args)...)

所以目前还不清楚这是否允许。

【讨论】:

  • 我通过标准语言链阅读了第二遍Effects: Constructs an object of type C at c。经过一段时间的思考,我没有看到任何迹象表明Constructs an object 会为实现添加的特殊情况转换留下空白,尤其是默认实现不允许此类事情这一事实证实了这一点。跨度>
  • char 已签名,因此在我看来将 std::byte 转换为 char 是一个错误
【解决方案2】:

Visual C++ 是错误的。 std::byte 是一个作用域枚举,声明如同enum class,因此除非使用显式转换,否则不能转换为char 或任何其他算术类型。

【讨论】:

    猜你喜欢
    • 2015-04-29
    • 2014-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-01
    • 1970-01-01
    • 2013-05-28
    相关资源
    最近更新 更多