std::scoped_allocator_adaptor和使用std::allocator_arg_t的构造函数的类 (注:这是一个提问标题,无需回答)

5

我在这里找到了一些词语: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)... );
所以,我进行了一个简单的测试。
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);
}

但是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"; }
};

这些行为是如何发生的?
2个回答

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无法从rvalue allocator中构造,所以construct调用应该不合法。
然而,我认为这是标准中的一个缺陷。考虑以下类型:
struct use_arg {
  using allocator_type = std::allocator<use_arg>;
  use_arg(allocator_type&&) { }
};
uses_allocatoris_constructible特性都为真,但调用scoped_allocator_adaptor::construct(pointer)将无法编译。检查is_constructible<T, inner_allocator_type>(测试从rvalue allocator构造)不一致,却传递了inner_allocator_type&(是lvalue),但这就是标准规定的。

1
问题是,您通过引用接收到了Alloc
std::is_constructible<T, std::allocator_arg_t, inner_allocator_type, Args...>::value==true

在您的情况下,inner_allocator只是std::scoped_allocator_adaptor<std::allocator<use_arg>>,不能转换为std::scoped_allocator_adaptor<std::allocator<use_arg>>&。您可以通过值或const-reference接收Alloc

std::is_constructible<use_a, int,std::scoped_allocator_adaptor<std::allocator<use_a>>>::value是什么情况?它也是false但是可以构造。 - linux40
@linux40 看起来像是一个 bug,因为例如在 clang 中,没有这个检查,只检查 uses_allocator::value。 - ForEveR
gcc中也只有一个检查。 - ForEveR
@ForEveR,你说的“gcc中只有一个检查”是什么意思?请看<bits/uses_allocator.h>中第85行的is_constructible检查和第96行的uses_allocator检查。 - Jonathan Wakely
1
哦,你的意思是只检查了 is_constructible<T, allocator_arg_t, A, Args...>,没有检查 is_constructible<T, Args..., A>,对吧?第二个检查是多余的,因为如果为假,则尝试进行该构造将是不合法的,这是标准所要求的。问题在于标准存在缺陷,并且需要执行一个_不是_不合法的_不同_构造。 - Jonathan Wakely

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接