emplace_back在使用具有基类成员的结构体时出现错误?

huangapple go评论76阅读模式
英文:

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 &lt;vector&gt;

struct Foo
{
    int foo{};
};

struct Bar : public Foo
{
    int bar{};
};

int main()
{
    std::vector&lt;Bar&gt; barVec;
    
    // Works
    barVec.push_back({2, 3});
    
    // Doesn&#39;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*&amp;, int, int)’
  518 |           std::construct_at(__p, std::forward&lt;_Args&gt;(__args)...);

...

/usr/include/c++/11/bits/stl_construct.h:96:17: error: could not convert ‘std::declval()’ from ‘int’ to ‘Foo’
   96 |     -&gt; decltype(::new((void*)0) _Tp(std::declval&lt;_Args&gt;()...))
      |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |                 |
      |                 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

-->

huangapple
  • 本文由 发表于 2023年5月15日 02:25:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76249060.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定