英文:
emplace_back error using struct with base class members?
问题
在以下示例中,我有一个基本结构和一个派生结构,每个结构都有一个成员,以及一个派生类型的向量。当我尝试向向量中添加元素时,push_back按预期工作。但是,当尝试使用emplace_back时,我会得到编译错误。
#include <vector>
struct Foo
{
int foo{};
};
struct Bar : public Foo
{
int bar{};
};
int main()
{
std::vector<Bar> barVec;
// Works
barVec.push_back({2, 3});
// Doesn't work
//barVec.emplace_back(2, 3);
return 0;
}
如果我将第一个参数包装为Foo
,它将可以工作。
// Works
barVec.emplace_back(Foo{2}, 3);
我有点理解发生了什么(关于std::allocator_traits::construct
的工作方式的一些内容),但是对具体细节感到困惑。push_back和emplace_back执行构造对象的步骤是什么,为什么原始的emplace_back失败了?
这里只翻译了您的问题,不包括代码部分。
英文:
In the following example, I have a base and derived struct, each with a single member, and a vector of the derived type. When I try to push_back to the vector, it works as expected. However, I get a compilation error when trying to use emplace_back.
#include <vector>
struct Foo
{
int foo{};
};
struct Bar : public Foo
{
int bar{};
};
int main()
{
std::vector<Bar> barVec;
// Works
barVec.push_back({2, 3});
// Doesn't work
//barVec.emplace_back(2, 3);
return 0;
}
/usr/include/c++/11/bits/alloc_traits.h:518:28: error: no matching function for call to ‘construct_at(Bar*&, int, int)’
518 | std::construct_at(__p, std::forward<_Args>(__args)...);
...
/usr/include/c++/11/bits/stl_construct.h:96:17: error: could not convert ‘std::declval()’ from ‘int’ to ‘Foo’
96 | -> decltype(::new((void*)0) _Tp(std::declval<_Args>()...))
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| int
If I wrap the first argument as a Foo
however, it works.
// Works
barVec.emplace_back(Foo{2}, 3);
I kind of understand what's going on (something about how std::allocator_traits::construct
works) but I'm confused about the specifics. What are the steps that push_back and emplace_back take to construct the object, and why does the original emplace_back fail?
答案1
得分: 2
Parenthesized aggregate initialization doesn't support brace elision. (§dcl.init)
Bar b1(2,3);
would fail.
Bar b2(Foo(2),3)
,
Bar b2(Foo{2},3)
,
Bar b2({2},3)
* would success
*since there is no way to pass {2}
(as braced-init-list) around, you cannot use it at vector::emplace_back
either.
英文:
Parenthesized aggregate initialization doesn't support brace elision. (§dcl.init)
Bar b1(2,3);
would fail.
Bar b2(Foo(2),3)
,
Bar b2(Foo{2},3)
,
Bar b2({2},3)
* would success
*since there is no way to pass {2}
(as braced-init-list) around, you cannot use it at vector::emplace_back
either.
<!-- keep simple?
std::construct_at doesn't try brace-initialization
https://eel.is/c++draft/dcl.init#general-16.6.2.2
https://timsong-cpp.github.io/cppwp/n4861/dcl.init#17.6.2.2
-->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论