How should I make sure that a constructor is noexcept if the allocator does not throw?
Here is an MRE:
#include <iostream>
#include <array>
#include <vector>
#include <memory_resource>
#include <concepts>
#include <cstddef>
template < std::unsigned_integral T, class Allocator = std::allocator<T> >
class Foo
{
std::vector<T, Allocator> vec;
public:
Foo( const size_t size, const T value,
const Allocator& alloc = Allocator { } ) noexcept( noexcept( Allocator { } ) )
: vec { size, value, alloc }
{
}
};
int main( )
{
Foo<unsigned> my_foo { 10, 505 };
auto buffer { std::array<std::byte, 50> { } };
std::pmr::monotonic_buffer_resource rsrc { buffer.data( ), buffer.size( ) };
Foo< unsigned, std::pmr::polymorphic_allocator<unsigned> > my_foo_pmr { 10, 505, &rsrc };
std::cout << std::boolalpha
<< noexcept( std::pmr::polymorphic_allocator<unsigned> { } ) << '\n' // true
<< noexcept( std::allocator<unsigned> { } ) << '\n' // true
<< std::noboolalpha;
}
First of all, I wonder why does noexcept( std::allocator<unsigned> { } ) return true? Is std::allocator<unsigned> exception safe? Like a vector with this allocator never throws? And what about the pmr allocator that has a stack-based buffer? Can it throw?
Secondly, what is the proper way of ensuring that the above class's ctor is marked noexcept if it actually never throws?
Because constructing a
std::allocator<unsigned>does not throw.The proper way is to not mark it as
noexceptbecause it may throw. The vector constructor you are calling is notnoexcept. Onlystd::vectorsdefault constructor isnoexcept( noexcept(Allocator()), but you are calling a different constructor. With apmrallocator I suppose nothing is different, because whensizeis too big then being able to construct the allocator without exceptions does not help to avoid running out of memory once you allocate too many elements.