MSVC 2015 为 std::vector 选择不正确的构造函数重载

Posted

技术标签:

【中文标题】MSVC 2015 为 std::vector 选择不正确的构造函数重载【英文标题】:MSVC 2015 choosing incorrect constructor overload for std::vector 【发布时间】:2016-07-07 17:39:27 【问题描述】:

以下是我的矩阵类的一部分,它具有动态的行数和列数,该类使用std::vector 以行优先顺序存储矩阵元素。


dynamic_matrix

template<typename _Ty,
    class _Alloc = std::allocator<_Ty>
> class dynamic_matrix 
public:
    typedef _Ty value_type;
    typedef std::size_t size_type;
    typedef _Alloc allocator_type;
    // various other typedefs, not relevant here...
    explicit dynamic_matrix(size_type _rows, size_type _cols, const _Alloc& alloc = _Alloc())
        : mtx(_rows*_cols, alloc), rows_(_rows), cols_(_cols) 
    explicit dynamic_matrix(size_type _rows, size_type _cols, const value_type& _val,
        const _Alloc& alloc = _Alloc()) : mtx(_rows*_cols, _val, alloc), rows_(_rows), cols_(_cols) 
    // other constructors and methods omitted...
private:
    std::vector<_Ty, _Alloc> mtx;
    size_type rows_;
    size_type cols_;
;

当我尝试使用上面显示的 sn-p 中的第一个构造函数和以下测试构造 dynamic_matrix 时,

int main(void) 
    dynamic_matrix<int> dm(10,10);

我从MSVC 2015 收到以下错误:

std::vector<_Ty,_Alloc>::vector(std::initializer_list<int>,const std::allocator<_Ty>&)
: cannot convert argument 2 from 'const std::allocator<_Ty>' to 'const int&'

而在GCC 6.1.0 中使用以下命令编译它不会产生警告或错误,

g++-6.1.0 --std=c++14 -Wall -pedantic -o maintest main.cpp dynamic_matrix.h

在上面的 dynamic_matrix 代码 sn-p 中使用第二个构造函数可以很好地编译 GCC 和 MSVC。

问题似乎是 MSVC 出于某种原因将构造函数调用 mtx(_rows*_cols, alloc) 解释为来自此 reference 的第 7 个构造函数,这将解释 cannot convert from const std::allocator to const int&amp; 错误消息。而 GCC 似乎按照我的意图使用了上述参考中的第三个构造函数。

为什么 MSVC 没有选择正确的构造函数来从 std::vector 调用而 GCC 是,我可以做些什么来缓解这种情况?

【问题讨论】:

如果你改用mtx_rows*_cols, alloc会发生什么? 恐怕仍然会出现同样的错误。 如果分配器对您来说不是那么重要,如果您忽略它,它就会起作用。 实际上...如果我查看 MSVC 中的 STL 源代码,我看不到一个接受计数和分配器的构造函数。我可能会误解这一点,但我认为您尝试使用的构造函数在 MSVC 中根本不存在,无论是否偶然。但是,有一个用于计数、填充值和分配器的构造函数,因此您可以考虑使用它。 【参考方案1】:

状态更新

该错误已修复并在 VS 2015 Update 3 中发布


查看 MSVS 中的矢量头,没有带有表单的构造函数

explicit vector( size_type count, const Allocator& alloc = Allocator() )

但它确实有

explicit vector(size_type _Count)

这是一个 C++11 添加的构造函数,在 C++14 中更改为以前的构造函数。看来 MSVS 还没有跟上这种变化。

真正奇怪的是vector&lt;bool&gt; 的特化确实在头文件中有正确的构造函数,如果你使用

dynamic_matrix<bool> dm(10, 10);

它会编译。

我已经向 MS 提交了错误报告,您可以看到它here

在解决此问题之前,您可以使用以下形式的构造函数

vector( size_type count, 
             const T& value,
             const Allocator& alloc = Allocator());

并提供一个值来构造元素。

【讨论】:

我明白了,感谢您的错误报告 - 我本以为 MS 现在已经应用了此更改。 @ArchbishopOfBanterbury 这里也是。它一定被忽略了/有人检查了它但忘了做这项工作;) @ArchbishopOfBanterbury 添加了一个可能的解决方法。 是的,这行得通,我可以使用该构造函数并将值默认初始化为第二个参数。

以上是关于MSVC 2015 为 std::vector 选择不正确的构造函数重载的主要内容,如果未能解决你的问题,请参考以下文章

错误与否? Visual Studio 2013 预览 std::vector 初始化列表与 std::string

这是 MSVC++ 2017 更新 3 中的编译器错误吗

将一行 cv::Mat 转换为 std::vector

有没有更惯用的方法来拆分 std::vector?

将 std::vector<uint8_t> 转换为 QImage

将数据从 std::vector 传递到 std::valarray 的最有效方法