How to fix this deprecated use of std::allocator?
Asked Answered
T

2

5

Here are the key points:

1: This project uses the open-source repository NanoRT as a raytracer in a project.

2: This project is compiled under Visual Studio 2019 (C++17)

3: This project is compiled with warnings treated as errors (and this cannot be changed). Adding the define to suppress these warnings did not help.

However, it looks like part of this code does not work in C++17, as it uses something that has become deprecated: (line 133 and 134 in the link I provided)

  typedef typename std::allocator<T>::pointer pointer;
  typedef typename std::allocator<T>::size_type size_type;

I need to figure out how to approach fixing this. The error suggests using std::allocator_traits but I am really unfamiliar with this use of std::allocator or allocator_traits.

Looking at the source, is this a few-line fix, or is this much more complicated than that and would require restructuring large portions of the code?

It looks like pointer is used as the return for allocate() and the first argument to deallocate(), with size_type being used in the same way.

  // Actually do the allocation. Use the stack buffer if nobody has used it yet
  // and the size requested fits. Otherwise, fall through to the standard
  // allocator.
  pointer allocate(size_type n, void *hint = 0) {
    if (source_ != NULL && !source_->used_stack_buffer_ &&
        n <= stack_capacity) {
      source_->used_stack_buffer_ = true;
      return source_->stack_buffer();
    } else {
      return std::allocator<T>::allocate(n, hint);
    }
  }

  // Free: when trying to free the stack buffer, just mark it as free. For
  // non-stack-buffer pointers, just fall though to the standard allocator.
  void deallocate(pointer p, size_type n) {
    if (source_ != NULL && p == source_->stack_buffer())
      source_->used_stack_buffer_ = false;
    else
      std::allocator<T>::deallocate(p, n);
  }
Tomtit answered 1/7, 2020 at 17:24 Comment(0)
C
6

There's a couple of ways to address this, and one size doesn't fit all.

The simplest path:

For std::allocator<T>, the type std::size_t is always the same as size_type, and the type T* is always the same as pointer. So the easiest thing is to just sub in those types.

The std::allocator_traits path:

These types also exist as nested types of the type std::allocator_traits<std::allocator<T>>. So you can access them like this:

std::allocator_traits<std::allocator<T>>::pointer

It is common to create type aliases to cut down on the verbosity:

using pointer = std::allocator_traits<std::allocator<T>>::pointer;

Irony: allocator<T>::size_type is "de-deprecated" in C++20.

Caret answered 1/7, 2020 at 17:58 Comment(3)
If I try replacing typedef typename std::allocator<T>::pointer pointer; with using pointer = std::allocator_traits<std::allocator<T>>::pointer; I get a large number of errors. Some syntax, but allocate() states "unknown override specifier. Is the using``` syntax the same as typedef typename here or does the usage need to change?Tomtit
It looks like if I use your approach, but with typedef typename instead, it works great. Thanks!Tomtit
Right. Sprinkle with typename until you get the desired results. ;-)Caret
V
0

Replace std::allocator<T>::pointer with T* and std::allocator<T>::size_type with std::size_t. That is what those deprecated member type aliases are defined as.

is this a few-line fix, or is this much more complicated than that and would require restructuring large portions of the code?

This seems like a trivial change.

The error suggests using std::allocator_traits

std::allocator_traits should be used if the allocator type is templated. That appears to not be the case here, and so using std::allocator_traits would be unnecessary.

But if we were to fix the problem in a case where the allocator is templated: Let's say the template argument is Alloc. Then you should replace Alloc::pointer with std::allocator_traits<Alloc>::pointer and Alloc::size_type with std::allocator_traits<Alloc>::size_type.

However, it looks like part of this code does not work in C++17, as it uses something that has become deprecated

Actually, use of deprecated features still works. It should still be fixed though since it will stop working in C++20. std::allocator<T>::pointer has been removed in C++20.

Viceroy answered 1/7, 2020 at 17:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.