I am trying to compile PDFium taken from the chromium source code with MSVC 141. The code is a custom allocator. You can see that the custom allocator can be instantiated with wchar_t no problem. wchar_t is apparently arithmetic. However, passing it into a vector fails the static assertions. The following code gives a static assertion, which I do not expect:
#include <iostream>
#include <type_traits>
#include <vector>
template <typename T>
struct FxAllocAllocator {
public:
static_assert(std::is_arithmetic<T>::value,
"Only numeric types allowed in this partition");
using value_type = T;
using pointer = T*;
using const_pointer = const T*;
using reference = T&;
using const_reference = const T&;
using size_type = size_t;
using difference_type = ptrdiff_t;
template <typename U>
struct rebind {
using other = FxAllocAllocator<U>;
};
FxAllocAllocator() noexcept = default;
FxAllocAllocator(const FxAllocAllocator& other) noexcept = default;
~FxAllocAllocator() = default;
template <typename U>
FxAllocAllocator(const FxAllocAllocator<U>& other) noexcept {}
pointer address(reference x) const noexcept { return &x; }
const_pointer address(const_reference x) const noexcept { return &x; }
pointer allocate(size_type n, const void* hint = 0) {
return static_cast<pointer>(FX_AllocOrDie(n, sizeof(value_type)));
}
void deallocate(pointer p, size_type n) { FX_Free(p); }
size_type max_size() const noexcept {
return std::numeric_limits<size_type>::max() / sizeof(value_type);
}
template <typename U, typename... Args>
void construct(U* p, Args&&... args) {
new (reinterpret_cast<void*>(p)) U(std::forward<Args>(args)...);
}
template <typename U>
void destroy(U* p) {
p->~U();
}
// There's no state, so they are all the same,
bool operator==(const FxAllocAllocator& that) { return true; }
bool operator!=(const FxAllocAllocator& that) { return false; }
};
int main()
{
std::cout << "wchar_t: " << std::is_arithmetic<wchar_t>::value << '\n';
FxAllocAllocator<uint8_t> success;
std::vector<wchar_t, FxAllocAllocator<wchar_t>> fail;
}
This is beyond my skills to figure out. My guess so far is that the MSVC compiler works differently than GCC, or I am missing a compiler option. I've tried MSVC 141 and 142. C++11 up to c++17. Can anyone explain to my why this does not compile?
It seems that the Visual Studio debug runtime code has a section in the destructor of std::vector
that assumes iterator debugging. I can't post the code here, due to probable copyright issues.
My guess is that the debug runtime expects the allocators to be stock Visual C++ allocators, with debugging information. Someone will correct me if I'm wrong, but this is where the static_assert
is pointing to.
What you can do is build a Release mode only, since a release build does not invoke the debug library code.
However, if you desire to easily debug the application you can:
1) Set the iterator level to 0 (_ITERATOR_DEBUG_LEVEL
preprocessor symbol should be 0) and rebuild
or
2) Create another configuration (call it Release With Debug
) and copy the same settings for Release
, except that the optimizations should be turned off.