【问题标题】:Deprecation of std::allocator<void>弃用 std::allocator<void>
【发布时间】:2018-05-09 02:42:10
【问题描述】:

相关:Why do standard containers require allocator_type::value_type to be the element type?

据说从 C++17 开始,以下内容已被弃用:

template<>
struct allocator<void>;

我想知道它是否已被弃用,因为单独的主模板现在能够容纳allocator&lt;void&gt;,或者allocator&lt;void&gt; 的用例已被弃用。

如果是后者,我想知道为什么。我认为allocator&lt;void&gt; 在指定不绑定到特定类型的分配器时很有用(所以只是一些模式/元数据)。

【问题讨论】:

标签: c++ memory-management c++17 c++-standard-library allocator


【解决方案1】:

并不是 std::allocator&lt;void&gt; 被弃用,只是它不是一个明确的专业化。

它过去的样子是这样的:

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&lt;T&gt;::referencestd::allocator&lt;T&gt;::const_reference 已被弃用,因此不需要对 void 进行显式特化。你可以只使用std::allocator&lt;void&gt;,连同std::allocator_traits&lt;std::allocator&lt;void&gt;&gt;::template rebind&lt;U&gt; 来获得std::allocator&lt;U&gt;,你只是不能实例化std::allocator&lt;void&gt;::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);
}

【讨论】:

    【解决方案2】:

    根据p0174r0

    同样,std::allocator&lt;void&gt; 被定义为使各种模板 重新绑定技巧可以在原始 C++98 库中工作,但它是 不是真正的分配器,因为它缺少allocatedeallocate 成员函数,默认情况下无法从 allocator_traits。这种需求随着 C++11 和 void_pointer 而消失了 和 const_void_pointer 在 allocator_traits 中键入别名。然而,我们 继续指定它以避免破坏旧代码 根据 C++11,尚未升级以支持通用分配器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多