Ego*_*gor 5 c++ visual-studio c++11 visual-studio-2017
我正在将我的项目从VS2015迁移到VS2017,这当然不会顺利进行。
我看到奇怪的编译器错误,可以通过以下代码重现该错误:
struct MoveOnly
{
MoveOnly() {}
MoveOnly(const MoveOnly&) = delete;
MoveOnly& operator = (const MoveOnly&) = delete;
MoveOnly(MoveOnly&&) = default;
MoveOnly& operator = (MoveOnly&&) = default;
bool operator == (const MoveOnly& rhs)const{return false;}
};
struct Hasher
{
size_t operator()(const MoveOnly&)const{return 0;}
};
std::vector < std::unordered_map<MoveOnly, int, Hasher> > test;
test.emplace_back();
Run Code Online (Sandbox Code Playgroud)
我可以使用所有编译器(gcc 7.2,clang 5.0.0,icc 18以及MSVC 2015)成功编译此代码。请点击以下链接查看测试:https :
//godbolt.org/g/uSqwDJ。在MSVC 2017(19.10.25017)上,但是由于编译器尝试引用MoveOnly类型已删除的副本构造函数而导致错误。对于我来说,此错误意义不大,因为没有理由在此处复制任何内容而不是移动。/std:c++14,/std:c++17,/std:c++latest不帮。此外,gcc和clang正确处理代码的事实使我对msvc 2017编译器感到怀疑。
更新:
之后Yakk发现的问题是什么,我想代替使用其他容器unordered_map和代码只编译vector。
所以问题似乎是这样的:
static_assert( noexcept(std::unordered_map<MoveOnly, int, Hasher>( std::declval<std::unordered_map<MoveOnly, int, Hasher>&&>())), "");
Run Code Online (Sandbox Code Playgroud)
您的编译器认为std::unordered_map<MoveOnly, int, Hasher>无法进行noexcept移动构造。
然后,std::vectorMSVC 2017附带的偏执狂实现会回退到复制元素上,从而在向量调整大小方面产生强大的异常保证。
复制显然是不可能的。
现在也是如此std::unordered_map<int, int>-MSVC认为移动它也有引发异常的风险;我相信您无法使用键或哈希类型做的任何事情都可能使unordered_map异常构造的move构造函数安全。
有没有很好的理由unordered_map(unordered_map&&)来不为noexcept。我不确定该标准是否允许它或强制它,或者它是否是编译器中的错误。如果该标准要求它为noexcept(false),则该标准存在缺陷。
您可以通过存储unique_ptrs 的向量来解决此问题。或者编写value_ptr对代码进行较少更改的异常处理:
template<class T>
struct value_ptr {
std::unique_ptr<T> raw;
value_ptr() noexcept(true)
{
try {
raw = std::make_unique<T>();
} catch (...) {}
}
template<class T0, class...Ts,
std::enable_if_t<!std::is_same<value_ptr, std::decay_t<T0>>{}, bool> =true
>
value_ptr(T0&& t0, Ts&&...ts) noexcept(true)
{
try {
raw=std::make_unique<T>( std::forward<T0>(t0), std::forward<Ts>(ts)... )
} catch(...) {}
}
value_ptr(value_ptr&& o)noexcept(true)=default;
value_ptr(value_ptr const& o)noexcept(true)
{ try {
if (o.raw)
raw = std::make_unique<T>(*o.raw);
}catch(...){}
}
value_ptr& operator=(value_ptr&& o)noexcept(true)=default;
value_ptr& operator=(value_ptr const& o)noexcept(true)
{ try {
if (o.raw)
raw = std::make_unique<T>(*o.raw);
}catch(...){}
return *this;
}
T* operator->() const { return raw.get(); }
T& operator*() const { return *raw; }
explicit operator bool() const { return (bool)raw; }
};
Run Code Online (Sandbox Code Playgroud)
这是我的测试工具:
template<class M>
void test_M() {
static_assert( noexcept(M( std::declval<M&&>())), "");
std::vector < M > test;
test.emplace_back();
}
void foo()
{
using M0=value_ptr<std::unordered_map<MoveOnly, int, Hasher>>;
using M1=std::unique_ptr<std::unordered_map<MoveOnly, int, Hasher>>;
test_M<M0>();
test_M<M1>();
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
645 次 |
| 最近记录: |