2016-01-15 8 views
5

I http://en.cppreference.com/w/cpp/memory/scoped_allocator_adaptor/constructstd :: scoped_allocator_adaptor und eine Klasse mit einem Konstruktor std :: allocator_arg_t

wenn std::uses_allocator<T, inner_allocator_type>::value==true einige Worte hier finden (die Art T verwendet Verteilern, zum Beispiel ist es, einen Behälter)

und wenn std::is_constructible<T, std::allocator_arg_t, inner_allocator_type, Args...>::value==true,

ruft dann

std::allocator_traits<OUTERMOST>::construct(OUTERMOST(*this), 
              p, 
              std::allocator_arg, 
              inner_allocator(), 
              std::forward<Args>(args)...); 

Also, ich habe einen einfachen Test

struct use_arg { 
    template <typename Alloc> 
    use_arg(std::allocator_arg_t, Alloc &, int i) 
     { std::cout << i << " in use_arg()\n"; } 
}; 

namespace std { 

template <typename A> struct uses_allocator<use_arg, A>: true_type {}; 

} // namespace std 

void test_scoped() 
{ 
    std::scoped_allocator_adaptor<std::allocator<use_arg>> sa; 
    auto p = sa.allocate(1); 
    sa.construct(p, 4); 
    sa.destroy(p); 
    sa.deallocate(p, 1); 
} 

aber gcc und Klirren geben Sie mir diese Fehler https://gist.github.com/anonymous/3e72754a7615162280fb

ich auch use_a schreiben use_arg zu ersetzen. Es könnte erfolgreich ausgeführt werden.

struct use_a { 
    template <typename Alloc> 
    use_a(int i, Alloc &) { std::cout << i << " in use_a()\n"; } 
}; 

Was bewirkt diese Verhaltensweisen?

Antwort

3

Ich denke, sowohl libstdC++ als auch libC++ tun genau das, was der Standard für das Beispiel des OP erfordert.

uses_allocator<use_arg, allocator<use_arg>> ist wahr, aber is_constructible<use_arg, allocator_arg_t, inner_allocator_type, int> ist falsch, weil use_arg nicht konstruierbar aus rvalue Allocator ist, so dass der construct Anruf schlecht gebildet werden soll.

Allerdings denke ich, es ist ein Defekt im Standard. Betrachten Sie diese Art:

struct use_arg { 
    using allocator_type = std::allocator<use_arg>; 
    use_arg(allocator_type&&) { } 
}; 

Die uses_allocator und is_constructible Züge sind beide richtig, aber ruft scoped_allocator_adaptor::construct(pointer) wird nicht kompiliert.

Es ist inkonsistent zu überprüfen is_constructible<T, inner_allocator_type> (die Tests für die Konstruktion von einem Rvalue Allocator), aber dann übergeben inner_allocator_type& (was ist ein Lvalue), aber das ist, was der Standard sagt.

1

Problem ist, dass Sie Alloc per Referenz erhalten.

std::is_constructible<T, std::allocator_arg_t, inner_allocator_type, Args...>::value==true 

hier in Ihrem Fall inner_allocator ist nur std::scoped_allocator_adaptor<std::allocator<use_arg>> und es nicht zu std::scoped_allocator_adaptor<std::allocator<use_arg>>& umgewandelt werden kann. Sie können Alloc nach Wert oder const-reference erhalten.

+0

Was ist mit 'std :: ist_konstruierbar >> :: value'? Es ist auch "falsch", könnte aber konstruiert werden. – linux40

+0

@ linux40 das sieht wie ein Fehler aus, da zum Beispiel in clang, gibt es keine Überprüfung, nur uses_allocator :: value ist aktiviert. – ForEveR

+0

gibt es nur einen Check in gcc auch. – ForEveR

Verwandte Themen