2

Entschuldigung, wenn es eine Lösung in einer ähnlichen Frage gibt, konnte ich keine mit ähnlicher Fehlerausgabe/Problem finden.Perfekte Weiterleitung Vorlage Parameterpaket zu emplace_back - gescheiterte Kompilierung

Ich versuche, diesen Code zu kompilieren:

#include <vector> 
using namespace std; 

template< typename value_type > 
class obj 
{ 
    vector<value_type> m_v; 
    public: 

    template<class... vaList_t> 
    void _emplace_back(vaList_t&&... i_values) 
    { 
     m_v.emplace_back(forward<vaList_t>(i_values)...); 
    } 
}; 

int main() 
{ 
    obj<int> thing; 
    thing._emplace_back(1,2,3,4); 
    return 0; 
} 

jedoch mit kompilieren fehlschlägt:

In file included from /usr/include/x86_64-linux-gnu/c++/4.9/bits/c++allocator.h:33:0, 
       from /usr/include/c++/4.9/bits/allocator.h:46, 
       from /usr/include/c++/4.9/vector:61, 
       from 1: 
/usr/include/c++/4.9/ext/new_allocator.h: In instantiation of 'void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = int; _Args = {int, int, int, int}; _Tp = int]': 
/usr/include/c++/4.9/bits/alloc_traits.h:253:4: required from 'static std::_Require<typename std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::type> std::allocator_traits<_Alloc>::_S_construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = int; _Args = {int, int, int, int}; _Alloc = std::allocator<int>; std::_Require<typename std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::type> = void]' 
/usr/include/c++/4.9/bits/alloc_traits.h:399:57: required from 'static decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) std::allocator_traits<_Alloc>::construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = int; _Args = {int, int, int, int}; _Alloc = std::allocator<int>; decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) = <type error>]' 
/usr/include/c++/4.9/bits/vector.tcc:97:40: required from 'void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {int, int, int, int}; _Tp = int; _Alloc = std::allocator<int>]' 
13:3: required from 'void obj<value_type>::_emplace_back(vaList_t&& ...) [with vaList_t = {int, int, int, int}; value_type = int]' 
20:30: required from here 
/usr/include/c++/4.9/ext/new_allocator.h:120:4: error: new initializer expression list treated as compound expression [-fpermissive] 
    { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } 

Fragen:

  • Ist das syntaktisch korrekt für perfektes Forwarding einer Vorlage Parameterpaket? (wenn nicht was ist?)
  • Wie kann dieses Verhalten richtig erreicht werden?

Vielen Dank im Voraus.

Bearbeiten Sorry für jede Mehrdeutigkeit. Ich versuche, diese Vektorfunktion mit Typ-Signatur genannt zu nennen emplace_back:

template< class... Args > void emplace_back(Args&&... args); 

mit einem perfekten weitergeleitet, Template-Parameter Paket, das mehrere Elemente enthält, hinzugefügt werden.

zB:

  • "1,2,3,4" - fügen Sie 4 verschiedene Objekte an der Rückseite des Vektors über emplace_back
  • "wahr, falsch, falsch" - 3 verschiedene Objekte hinzufügen an der Rückseite des Vektors über emplace_back
+1

Vielleicht haben Sie bedeuten 'm_v.insert (m_v.end() {vorwärts (i_values) ...});' oder '(m_v.emplace_back (vorwärts (i_values)), ...); ' –

+1

Sie möchten 4 Elemente in den Vektor einfügen? – kennytm

+0

@PiotrSkotnicki das ", ..." kompiliert nicht. Das Insert kompiliert. Es ist jedoch nicht perfekt, das Parameterpaket weiterzuleiten. Die Funktionsargumente für das Einfügen sind ein Iterator und eine Initialisierungsliste, verursacht also zusätzlichen Overhead? – QuantumKarl

Antwort

4

c.emplace_back erzeugt ein einzelnes Element in c. Wenn Sie mehrere wollen, müssen Sie emplace_back Teil der Erweiterung machen. Etwas wie folgt aus:

template<class... vaList_t> 
void _emplace_back(vaList_t&&... i_values) 
{ 
    int dummy[] = { 0, (m_v.emplace_back(forward<vaList_t>(i_values)), 0)... }; 
} 

[Live example]

+0

Danke. Ich sehe jetzt: "Hängt ein neues Element an das Ende des Containers." (Die Template-Parameterversion ist für Objekte mit mehreren Argumenten, notieren Sie mehrere Objekte). – QuantumKarl

+0

@QuantumKarl Genau. Die wahre Stärke von 'emplace_back' gegenüber' push_back' besteht darin, dass Sie das Element direkt im Container konstruieren können (anstatt es zu kopieren/zu verschieben), indem Sie die Konstruktorargumente ganz nach unten übergeben. – Angew