std::allocator<void>的弃用

18

相关内容:为什么标准容器要求allocator_type::value_type必须是元素类型?

据说以下内容自C++17起已被弃用:

template<>
struct allocator<void>;

我想知道它是否被弃用,因为主要模板现在已经能够容纳allocator<void>,还是allocator<void>的使用情况被废弃了。

如果是后者,我想知道原因。我认为allocator<void>在指定未绑定到特定类型(仅为某些架构/元数据)的分配器时很有用。


这里有一个关于编程的讨论:https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/L0IolOWBKPA - Angel Koh
1
试图ping @NicolBolas,他参与了讨论,这个问题对我来说也很有趣。 - SergeyA
2个回答

4
根据p0174r0
同样地,std::allocator被定义为各种模板重新绑定技巧在原始的C++98库中能够工作,但它不是一个实际的分配器,因为它缺少allocate和deallocate成员函数,这些函数不能从allocator_traits中默认合成。这个需要在C++11中消失了,并且在allocator_traits中有了void_pointer和const_void_pointer类型别名。然而,我们继续指定它,以避免破坏尚未升级以支持通用分配器的旧代码,根据C++11的规定。

4

并不是说std::allocator<void>已经过时了,只是它不是一个显式的特化。

它曾经的样子大概是这样的:

template<class T>
struct allocator {
    typedef T value_type;
    typedef T* pointer;
    typedef const T* const_pointer;
    // These would be an error if T is void, as you can't have a void reference
    typedef T& reference;
    typedef const T& const_reference;

    template<class U>
    struct rebind {
        typedef allocator<U> other;
    }

    // Along with other stuff, like size_type, difference_type, allocate, deallocate, etc.
}

template<>
struct allocator<void> {
    typedef void value_type;
    typedef void* pointer;
    typedef const void* const_pointer;

    template<class U>
    struct rebind {
        typdef allocator<U> other;
    }
    // That's it. Nothing else.
    // No error for having a void&, since there is no void&.
}

现在,由于std :: allocator :: reference和std :: allocator :: const_reference已被弃用,因此不需要为void进行显式特化。您可以使用std :: allocator ,以及std :: allocator_traits > :: template rebind 来获取std :: allocator ,但是您不能实例化std :: allocator :: allocates。
例如:
template<class Alloc = std::allocator<void>>
class my_class;  // allowed

int main() {
    using void_allocator = std::allocator<void>;
    using void_allocator_traits = std::allocator_traits<void_allocator>;
    using char_allocator = void_allocator_traits::template rebind_alloc<char>;
    static_assert(std::is_same<char_allocator, std::allocator<char>>::value, "Always works");

    // This is allowed
    void_allocator alloc;

    // These are not. Taking the address of the function or calling it
    // implicitly instantiates it, which means that sizeof(void) has
    // to be evaluated, which is undefined.
    void* (void_allocator::* allocate_mfun)(std::size_t) = &void_allocator::allocate;
    void_allocator_traits::allocate(alloc, 1);  // calls:
    alloc.allocate(1);
}

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