I find some words here http://en.cppreference.com/w/cpp/memory/scoped_allocator_adaptor/construct
if
std::uses_allocator<T, inner_allocator_type>::value==true
(the type T uses allocators, e.g. 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 do 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 could run successfully.
struct use_a {
template <typename Alloc>
use_a(int i, Alloc &) { std::cout << i << " in use_a()\n"; }
};
What makes these behaviors happen?
I think both libstdc++ and libc++ are doing exactly what the standard requires for the OP's example.
uses_allocator<use_arg, allocator<use_arg>>
is true, but is_constructible<use_arg, allocator_arg_t, inner_allocator_type, int>
is false because use_arg
is not constructible from an rvalue allocator, so the construct
call should be ill-formed.
However, I think it's 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
traits are both true, but calls to scoped_allocator_adaptor::construct(pointer)
will fail to compile.
It is inconsistent to check is_constructible<T, inner_allocator_type>
(which tests for construction from an rvalue allocator) but then pass inner_allocator_type&
(which is an lvalue), but that's what the standard says.
Problem is, that you receives Alloc
by reference.
std::is_constructible<T, std::allocator_arg_t, inner_allocator_type, Args...>::value==true
here in your case inner_allocator
is just 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 receives Alloc
by value, or by const-reference
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With