Reputation: 1283
Here is an example of allocator from cppreference:
#include <cstdlib>
#include <limits>
#include <new>
template<class T>
struct Mallocator
{
typedef T value_type;
Mallocator() = default;
template<class U>
constexpr Mallocator(const Mallocator<U>&) noexcept
{
}
[[nodiscard]] T* allocate(std::size_t n)
{
if (n > std::numeric_limits<std::size_t>::max() / sizeof(T))
throw std::bad_array_new_length();
if (auto p = static_cast<T*>(std::malloc(n * sizeof(T)))) {
return p;
}
throw std::bad_alloc();
}
void deallocate(T* p, std::size_t n) noexcept { std::free(p); }
};
template<class T, class U>
bool operator==(const Mallocator<T>&, const Mallocator<U>&)
{
return true;
}
template<class T, class U>
bool operator!=(const Mallocator<T>&, const Mallocator<U>&)
{
return false;
}
It can be used as in examples 1
and 2
in the following snippet:
#include "mallocator.h"
#include <vector>
int mainF()
{
std::vector<int, Mallocator<int>> v; // 1
Mallocator<int> a;
std::vector<int, Mallocator<int>> v2 { a }; // 2
std::vector<int, Mallocator<int>> v3 { a }; // 2
// std::vector<int> v4 { a }; // 3 (compilation error)
return 0;
}
Is it possible to conform custom allocator so it will work as in example 3
. If yes, how to do it?
Upvotes: -1
Views: 103
Reputation: 18090
std::vector<int>
is implicitly std::vector<int, std::allocator<int>>
, if you omit the second template argument it will be the default one, it will not be deduced from the constructor.
CTAD is all or none, so you can either generate your own alias, or apply CTAD to All template arguments.
#include "mallocator.h"
#include <vector>
template <typename T>
using MyVector = typename std::vector<T, Mallocator<T>>;
int main()
{
std::vector<int, Mallocator<int>> v; // 1
Mallocator<int> a;
std::vector<int, Mallocator<int>> v2 { a }; // 2
std::vector<int, Mallocator<int>> v3 { a }; // 2
std::vector v4 { a }; // let CTAD deduce both
MyVector<double> v5{ a };
return 0;
}
note that you cannot have std::vector<double> v5{a};
because CTAD isn't invoked, and you will have std::vector<double, std::allocator<double>> v5{a}
, which cannot compile.
Upvotes: 0
Reputation: 138
No, class template argument deduction (CTAD) doesn't allow this. But you can create a wrapper function and use partial template argument deduction with this function.
Something like this:
#include <memory>
#include <vector>
template <typename T, typename Allocator>
auto get_vector(const Allocator& a) {
return std::vector<T, Allocator>{a};
}
int main() {
// Insert your own allocator here.
std::allocator<int> some_random_allocator;
auto vec = get_vector<int>(some_random_allocator);
}
Upvotes: 0