Trying to write a generic code to emplace a default constructed object into an std container and return an iterator to it.
with insert the solution is
template
typename C::iterator insert(C& container)
{
return container.insert(container.end(), typename C::value_type());
}
But emplace has no such common interface so I had to specialize it for 2 container types.
My best attempt (that did not compile) was:
template
auto emplace(C& container)
-> decltype(container.emplace_back())
{
return container.emplace_back();
}
template
auto emplace(C& container)
-> decltype(container.emplace().first)
{
return container.emplace().first;
}
This causes: error: void value not ignored as it ought to be
and I don't understand why my decltype was deduced as void.
Used gcc 4.8.5 with -std=c++11
Edit:
reproduced by
int main()
{
std::vector v;
std::vector::iterator iv = emplace(v);
std::set s;
std::set::iterator is = emplace(s);
return 0;
}
Edit 2:
second attempt
template
auto emplace(C& container)
-> decltype(container.emplace().first)
{
return container.emplace().first;
}
template
auto emplace(C& container)
-> decltype(container.emplace(container.end()))
{
return container.emplace(container.end());
}
works for verctor, but set is ambiguous.
Answer
Finally solved it thanks to @Quentin:
// For vector, list and anything push_backable
template
auto emplace(C& container)
-> decltype(container.emplace_back(),container.rbegin())
{
container.emplace_back();
return container.rbegin();
}
// For set,unordered_set, and anything that emplace returns a pair.
template
auto emplace(C& container)
-> decltype(container.emplace().first)
{
return container.emplace().first;
}
No comments:
Post a Comment