See this answer for how to insert into stdmap without making copies of the map value.
std::map emplace without copying value
Continueing from that answer - suppose my Foo
type looks something like this:
struct Foo {
const int& intref_;
std::mutex mutex_;
}
Then initialized using aggregate-initialization like this
Foo{7}
or
Foo{7, std::mutex()}
Would it be somehow possible to be emplaced into the map with type ?:
std::map<size_t, Foo> mymap;
I know I could just write a constructor for Foo
- but can it be done with aggregate initialization instead ?
Link to compiler explorer:
Relevant c++ references:
https://en.cppreference.com/w/cpp/container/map/try_emplace
https://en.cppreference.com/w/cpp/language/aggregate_initialization
You may exploit casts to indirect your construction
template<typename T>
struct tag { using type = T; };
template<typename F>
struct initializer
{
F f;
template<typename T>
operator T() &&
{
return std::forward<F>(f)(tag<T>{});
}
};
template<typename F>
initializer(F&&) -> initializer<F>;
template<typename... Args>
auto initpack(Args&&... args)
{
return initializer{[&](auto t) {
using Ret = typename decltype(t)::type;
return Ret{std::forward<Args>(args)...};
}};
}
And use it as
struct Foo
{
const int& intref_;
std::mutex mutex_;
};
void foo()
{
int i = 42;
std::map<int, Foo> m;
m.emplace(std::piecewise_construct,
std::forward_as_tuple(0),
std::forward_as_tuple(initpack(i)));
}
Note you can't prolong a temporary's lifetime by binding it to a non-stack reference.