std :: scoped_allocator_adaptor和一个使用std :: allocator_arg_t的构造函数的类

lin*_*x40 5 c++ stl allocator c++11

我在这里找到一些词语http://en.cppreference.com/w/cpp/memory/scoped_allocator_adaptor/construct

if std::uses_allocator<T, inner_allocator_type>::value==true(类型T使用分配器,例如它是一个容器)

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

然后打电话

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

所以,我做了一个简单的测试

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);
}
Run Code Online (Sandbox Code Playgroud)

但是gcc和clang给了我这些错误https://gist.github.com/anonymous/3e72754a7615162280fb

我也写use_a了替换use_arg.它可以成功运行.

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

是什么让这些行为发生?

Jon*_*ely 3

我认为 libstdc++ 和 libc++ 都完全符合 OP 示例的标准要求。

uses_allocator<use_arg, allocator<use_arg>>为 true,但is_constructible<use_arg, allocator_arg_t, inner_allocator_type, int>为 false,因为use_arg不能从右值分配器构造,因此construct调用应该是格式错误的。

但是,我认为这是标准的缺陷。考虑这种类型:

struct use_arg {
  using allocator_type = std::allocator<use_arg>;
  use_arg(allocator_type&&) { }
};
Run Code Online (Sandbox Code Playgroud)

和特征都是正确的,但是调用将无法编译uses_allocator。is_constructiblescoped_allocator_adaptor::construct(pointer)

检查is_constructible<T, inner_allocator_type>(测试右值分配器的构造)然后通过inner_allocator_type&(这是左值)是不一致的,但这就是标准所说的。