Std :: scoped_allocator_adaptor and constructor class using std :: allocator_arg_t

I find here a few words http://en.cppreference.com/w/cpp/memory/scoped_allocator_adaptor/construct

if std::uses_allocator<T, inner_allocator_type>::value==true (type T uses distributors, for example. it is a container)

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

then calls

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

So, I am doing a simple 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); } 

but gcc and clang give me these errors https://gist.github.com/anonymous/3e72754a7615162280fb

I also write use_a to replace use_arg . It can work successfully.

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

What are these behaviors?

+5
source share
2 answers

I think that libstdC ++ and libC ++ do exactly what the standard requires for the OP example.

uses_allocator<use_arg, allocator<use_arg>> true, but is_constructible<use_arg, allocator_arg_t, inner_allocator_type, int> is false because use_arg not constructive from the value allocator r, so the construct call must be poorly formed.

However, I believe that this is a defect in the standard. Consider this type:

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

The uses_allocator and is_constructible are true, but scoped_allocator_adaptor::construct(pointer) calls are not compiled.

It is not is_constructible<T, inner_allocator_type> to check is_constructible<T, inner_allocator_type> (which checks the construction from rvalue allocator), but then pass inner_allocator_type& (which is lvalue), but that is what the standard says.

+3
source

The problem is that you get Alloc from the link.

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

here in your case inner_allocator is only std::scoped_allocator_adaptor<std::allocator<use_arg>> and it cannot be converted to std::scoped_allocator_adaptor<std::allocator<use_arg>>& . You can just get Alloc by value or const-reference .

+1
source

Source: https://habr.com/ru/post/1240685/


All Articles