Iterating over std::optional - c++

I tried to iterate over an std::optional:
for (auto x : optionalValue)
{
...
}
With the expectation of it doing nothing if optionalValue is empty but doing one iteration if there is a value within, like it would work in Haskell (which arguably made std::optional trendy):
forM optionalValue
( \x ->
...
)
Why can't I iterate an optional? Is there another more standard C++ method to do this?

std::optional does not have a begin() and end() pair. So you cannot range-based-for over it. Instead just use an if conditional.
See Alternative 2 for the closest thing to what you want to do.
Edit: If you have a temporary from a call result you don't have to check it explicitly:
if (auto const opt = function_call()) {
do_smth(*opt);
}
The check for static_cast<bool>(opt) is done implicitly by if.
Alternative 1
Another alternative is to not use an std::optional<T> but std::variant<std::monostate, T>. You can then either use the overloaded idiom or create a custom type to handle the monostate:
template <typename F>
struct MaybeDo {
F f;
void operator()(std::monostate) const {}
template <typename T>
void operator()(T const& t) const { f(t); }
};
which will allow you to visit the value with some function:
std::variant<std::monostate, int> const opt = 7;
std::visit(MaybeDo{[](int i) { std::cout << i << "\n"; }}, opt);
Alternative 2
You can also wrap optional in a thing that allows you to iterate over it. Idea:
template <typename T>
struct IterateOpt {
std::optional<T> const& opt;
struct It {
std::optional<T> const* p;
It& operator++() {
p = nullptr;
return *this;
}
It operator++(int) {
return It{nullptr};
}
auto const& operator*() const { **p; }
};
auto begin() const {
if (opt) return It{&opt};
else end();
}
auto end() const {
return It{nullptr};
}
};
This is a crude sketch of how to do this and probably requires some love to work on different situations (like a non-const optional).
You can use this to "iterate" over the optional:
for (auto const& v: IterateOpt{function_call()}) {
do_smth(v);
)

Related

Safe way to use string_view as key in unordered map

My type Val contains std::string thekey.
struct Val
{
std::string thekey;
float somedata;
}
I would like put my type in an unordered map, with thekey as key. For memory and conversion avoidance reasons I would like to have std::string_view as key type. Is it possible to have the key created to point to val.thekey, while using unique_ptr ?
std::unique_ptr<Val> valptr = ...;
std::unordered_map<std::string_view,std::unique_ptr<Val>> themap;
themap[std::string_view(valptr->thekey)] = std::move(valptr); // is this ok and safe?
Safe way to use string_view as key in unordered map
In general there isn't one, because the storage underlying the view might change at any time, invalidating your map invariants.
Associative containers generally own a const key precisely to avoid this.
In your specific case it makes much more sense to use std::unordered_set<Val, ValKeyHash, ValKeyEqual> with suitable hash and equality functors.
Edit, these suitable functors are simply
struct ValKeyHash {
std::size_t operator() (Val const &v)
{
return std::hash<std::string>{}(v.thekey);
}
};
struct ValKeyEqual {
bool operator() (Val const& a, Val const& b)
{
return a.thekey == b.thekey;
}
};
Obviously this leaves us with the slightly unhappy requirement of using a temporary Val{key, dummy_data} for lookups, at least until we can use the C++20 transparent/projected version in the other answer.
In c++20, you should do this
namespace utils {
// adl hash function:
template<class T>
auto hash( T const& t )
->decltype( std::hash<T>{}(t) )
{ return std::hash<T>{}(t); }
// Projected hasher:
template<class Proj>
struct ProjHash {
template<class T>
constexpr std::size_t operator()(T const& t)const {
return hash(Proj{}(t));
}
using is_transparent=std::true_type;
};
// Projected equality:
template<class Proj>
struct ProjEquals {
template<class T, class U>
constexpr std::size_t operator()(T const& t, U const& u)const {
return std::equal_to<>{}( Proj{}(t), Proj{}(u) );
}
using is_transparent=std::true_type;
};
}
// A projection from Val to a string view, or a string view
// to a string view:
struct KeyProj {
std::string_view operator()(Val const& val) const { return val.thekey; }
std::string_view operator()(std::string_view sv) const { return sv; }
};
std::unordered_set<Val, ProjHash<KeyProj>, ProjEquals<KeyProj>> theset;
now you can
theset.find("hello")
to find the element of the set whose key is "hello".
A map is fundamentally wrong here, because the features that a map has that the above set does not don't do the right things. Like mymap["hello"], which goes and creates a Val if it isn't found; we now have a dangling string view in the container.
An intrusive map in std is a set with a projection, not a map with a reference into the value as a key.

How to iterate (outside a class) a private member which is a vector<unique_ptr<T>>

class Organization {
private:
vector<unique_ptr<Employee>> employees_;
vector<unique_ptr<Item>> items_;
}org;
I need to have a facility outside the class to iterate over the employees and items and call their members, like the following...
for(auto const& e : getEmployees()) { e.get()->getName(); }
But I cannot make getEmployees() function to return employees_, as vector of unique_ptrs is not copyable
So currently I'm having a for_each_employee function
template<class callable>
void Organization::for_each_employee(callable f) {
for(auto const& e : employees_) {
f(e.get());
}
}
// And I use it like,
org.for_each_employee([](Employee* e){ e->getName(); });
But I do not like this idea as I'll have to write for_each_employee and for_each_item. I have similar other classes of the similar structure. So I will end up writing lot of for_each_XX type functions. This is not what I want.
Can I have generic for_each function that are friends of these classes (like Organization that contain vector of unique_ptrs)?
How to iterate (outside a class) a private member which is a vector<unique_ptr<T>>
The simplest and quite readable approach is to provide an access method that returns a possibly const-qualified reference to the data member. This way, you don't try to copy non-copyable members.
const vector<unique_ptr<Item>>& getItems()
{
return items_;
}
which can be used like this
for (const auto& item : organizationInstance.getItems())
item->doStuff();
You can return reference of employee_ in getEmployees() to iterate
const vector<unique_ptr<Employee>>& getEmployees()
{
return employee_;
}
What you're looking for is iterators. std::vector::begin() and std::vector::end() return iterators to the first and to the one-past-the-end elements of the vector. Then you can do stuff like.
for (auto iter = organization.get_employees_begin(); iter != organization.get_employees.end(); ++iter) {
do_something(*iter);
}
Where
class Organization {
auto get_employees_begin() { return employees_.begin(); }
auto get_employees_begin() const { return employees_.begin(); }
auto get_employees_end() { return employees_.end(); }
auto get_employees_end() const { return employees_.end(); }
}
The const versions return const iterators, which are similar to pointers-to-const in that they don't allow modification of the vector. The added benefit of this method over returning a reference to the vector is that it completely decouples the implementation from the interface. If you don't care about that for whatever reason, you can use this instead.
class Organization {
auto& get_employees() { return employees_; }
const auto& get_employees() const { return employees_; }
}
This will allow you to use all vector utilities but it will also make all your code that relies on them break if the internal container changes from a vector to something else.
In any case, you might not want to provide the non-const functions if the vector should not be modified directly.
To allow only iterating, not giving any more vector-specific operations You can use boost::range
auto getItems() {
return boost::make_iterator_range(employees_.begin(), employees_.end());
}
Here is a simple span class. It is similar to gsl::span. It represents a view into a contiguous buffer of T elements (like in an array):
template<class T>
struct span {
T* begin() const { return b; }
T* end() const { return e; }
T* data() const { return begin(); }
std::size_t size() const { return end()-begin(); }
bool empty() const { return size()==0; }
span( T* s, T* f ):b(s),e(f) {}
span( T* s, std::size_t length ):span(s, s+length){}
span() = default;
template<class A>
span( std::vector<T, A>& v ):
span(v.data(), v.length() )
{}
template<class A>
span( std::vector<std::remove_const_t<T>, A> const& v ):
span(v.data(), v.length() )
{}
template<std::size_t N>
span( T(& arr)[N] ):
span(arr, N)
{}
template<std::size_t N>
span( std::array<T, N>& arr ):
span(arr.data(), N)
{}
template<std::size_t N>
span( std::array<std::remove_const_t<T>, N> const& arr ):
span(arr.data(), N)
{}
private:
T* b = 0;
T* e = 0;
};
simply have your getEmployees return a span<std::unique_ptr<Employee> const>.
This exposes everything the caller needs to iterate over it efficiently, and no more.
The simpler alternative is to return a std::vector<std::unique_ptr<Employee>> const&, but that leaks implementation details that are utterly irrelevant to the consumer of getEmployee.

generic iterators to access elements of vectors without using Templates c++

I am creating a function which should take as input iterators to vector
for example:
vector<int> a;
foo(a.begin(),a.end())
The vector can hold any type.
Now the simple way to do this is using templates
template <typename Iterator>
void foo(Iterator first, Iterator last) {
for (Iterator it = first; it!=last; ++it) {
cout << *it;
}
}
I want to know if there is a way to achieve the same functionality without using templates. Since using Templates would force me to include these functions in Header file of a public API which I don't want to. So I wanted to know is there an alternate way to access the iterators without using Templates.
There are ways not to include the implementation in header files but they are not clean to implement (for instance you should know in advance the instantiations). Read here for more info about this issue:
Why can’t I separate the definition of my templates class from its declaration and put it inside a .cpp file?
How can I avoid linker errors with my template functions?
For instance in:
foo.h
#ifndef HI_
#define HI_
template<class Iterator>
void foo(Iterator first, Iterator last);
#endif
foo.cpp
#include "stack.h"
using namespace std;
template<class Iterator>
void foo(Iterator first, Iterator last) {
for (Iterator it = first; it != last; ++it) {
cout << *it << " ";
}
}
template
void foo( std::vector<int>::iterator first, std::vector<int>::iterator last);
template
void foo( std::vector<double>::iterator first, std::vector<double>::iterator last);
Now you can use foo function only for double and int. Other types won't link.
Hope this helps.
This is a long answer. The short answer is "type erasure"; go learn about it.
The long answer is two answers. First I cover "do you just want to be able to iterate over contiguous ints?". Then you want span. This is a really simple form of type erasure that forgets what the exact container is you are working on so long as it is contiguous and over T.
The second answer is if you actually need to deal with multiple types (not just int) and multiple kinds of containers (not just contiguous ones).
The two answers are separated by a line.
The span concept (see gsl::span) is designed for pretty much this reason. It itself is a template (over the type you are working with), but it will be a concrete instance of a template in most interfaces.
Here is a toy version of it:
template<class T>
struct span_t {
T* b = 0;
T* e = 0;
T* begin() const { return b; }
T* end() const { return e; }
span_t(span_t const&)=default;
span_t& operator=(span_t const&)=default;
span_t()=default;
span_t( T* s, T* f ):b(s),e(f) {}
span_t( T* s, std::size_t l):span_t(s, s+l){}
template<std::size_t N>
span_t( T(&arr)[N] ):span_t(arr, N) {}
std::size_t size() const { return end()-begin(); }
bool empty() const { return begin()==end(); }
T& front() const { return *begin(); }
T& back() const { return *(std::prev(end()); }
T* data() const { return begin(); }
span_t without_front( std::size_t N=1 ) const {
return {std::next( begin(), (std::min)(N, size()) ), end()};
}
span_t without_back( std::size_t N=1 ) const {
return {begin(), std::prev(end(), (std::min)(N, size()) )};
}
};
we can augment it with conversion operators
namespace details {
template<template<class...>class Z, class, class...Ts>
struct can_apply:std::false_type{};
template<class...>using void_t=void;
template<template<class...>class Z, class...Ts>
struct can_apply<Z, void_t<Z<Ts...>>, Ts...>:std::true_type{};
}
template<template<class...>class Z, class...Ts>
using can_apply = details::can_apply<Z,void,Ts...>;
template<class C>
using dot_data_r = decltype( std::declval<C>().data() );
template<class C>
using dot_size_r = decltype( std::declval<C>().size() );
template<class C>
using can_dot_data = can_apply< dot_data_r, C >;
template<class C>
using can_dot_size = can_apply< dot_size_r, C >;
can_dot_data detects via SFINAE if .data() is valid to do on an object of type C.
Now we add a constructor:
template<class T,
std::enable_if_t<
can_dot_data<T&>{}
&& can_dot_size<T&>{}
&& !std::is_same<std::decay_t<T>, span_t>{}
, int
> =0
>
span_t( T&& t ): span_t( t.data(), t.size() ) {}
which covers std::vector and std::string and std::array.
Your function now looks like:
void foo(span_t<int> s) {
for (auto&& e:s)
std::cout << s;
}
}
with use:
std::vector<int> a;
foo(a);
now, this only works for contiguous containers of a specific type.
Suppose this is not what you want. Maybe you do need to solve this for a myriad of types, and you don't want to expose everything in the header.
Then what you need to do is known as type erasure.
You need to work out what minimal set of operations you need from the provided types. Then you need to write wrappers that "type erase" these operations down to "typeless" operations.
This goes in the header, or in another helper header.
In the interface of the function, or in a header intermediate helper, you take the incoming types and do the type erasure, then pass the type-erased types into the "real" implementation.
An example of type erasure is std::function. It takes almost anything that can be invoked with a fixed signature, and turns it into a single type-erased type. Everything except how to copy, destroy and invoke an instance of the type is "forgotten" or erased.
For your case:
template <typename Iterator>
void foo(Iterator first, Iterator last) {
for (Iterator it = first; it!=last; ++it) {
cout << *it;
}
}
I see two things that need to be erased down to; iteration, and printing.
struct printable_view_t {
void const* data = 0;
void(*print_f)(std::ostream& os, void const*) = 0;
explicit operator bool()const{return data;}
printable_view_t() = default;
printable_view_t(printable_view_t const&) = default;
template<class T,
std::enable_if_t<!std::is_same<T, printable_view_t>{}, int> =0
>
printable_view_t( T const& t ):
data( std::addressof(t) ),
print_f([](std::ostream& os, void const* pv){
auto* pt = static_cast<T const*>(pv);
os << *pt;
})
{}
std::ostream& operator()(std::ostream& os)const {
print_f(os, data);
return os;
}
friend std::ostream& operator<<(std::ostream& os, printable_view_t p) {
return p(os);
}
};
printable_view_t is an example of type-erasing "I can be printed".
void bar( printable_view_t p ) {
std::cout << p;
}
void test_bar() {
bar(7);
bar(3.14);
bar(std::string("hello world"));
}
The next thing we'd have to do is type erase iteration. This is harder, because we want to type erase iteration over iterating over a printable_view_t type.
Type erasing foreach is a tad easier, and often more efficient.
template<class View>
struct foreach_view_t {
void* data = 0;
void(*func)( std::function<void(View)>, void* ) = 0;
explicit operator bool()const{return data;}
foreach_view_t() = default;
foreach_view_t(foreach_view_t const&) = default;
template<class T,
std::enable_if_t<!std::is_same<std::decay_t<T>, foreach_view_t>{}, int> =0
>
foreach_view_t( T&& t ):
data( const_cast<std::decay_t<T>*>(std::addressof(t)) ),
func([](std::function<void(View)> f, void* pv){
auto* pt = static_cast<std::remove_reference_t<T>*>(pv);
for (auto&& e : *pt)
f(decltype(e)(e));
})
{}
void operator()(std::function<void(View)> f)const{
func(f, data);
}
};
we then daisy chain these together
void foo(foreach_view_t<printable_view_t> x) {
x([](auto p){ std::cout << p; });
}
test code:
std::vector<int> a{1,2,3};
foo(a);
Now much of the header code was "hoisted" into the type erasure types instead of a function template body. But careful choice of the points of type erasure can let you keep what you need from the types precise and narrow, and the logic of how you use those operations private.
As an example, the above code doesn't care where you are printing it to; std::cout was not part of the type erasure.
Live example.
I want to know if there is a way to achieve the same functionality without using templates. [...] I wanted to know is there an alternate way to access the iterators without using Templates.
Yes, if you use C++14, but...
Since using Templates would force me to include these functions in Header file of a public API which I don't want to.
... isn't a useful way for you because it's equivalent to use templates and you have to put it in the header file.
In C++14 you can use a lambda function with auto parameters.
auto foo = [](auto first, auto last)
{ for (auto it = first ; it != last; ++it ) std::cout << *it; };
The autos aren't template (from a formal point of view) but are equivalent and you can't declare foo in the header and develop it in a cpp file.

c++ how to assert that all std::shared_ptr in a vector are referring to something

When I have a function receiving a (smart) pointer that is supposed to refer something, I always start as follows:
class Foo;
void doSomething(const std::shared_ptr<Foo>& pFoo)
{
assert(pFoo);
// ...
}
Now I am looking for a similar assert condition for a vector (or other container) of (smart) pointers. The best I could come up with is:
void doSomething(const std::vector<std::shared_ptr<Foo> >& pFoos)
{
assert(std::all_of(pFoos.begin(), pFoos.end(), [](const std::shared_ptr<Foo>& pFoo) { return pFoo; }));
// ...
}
I wonder whether this could be improved.. can the lambda be avoided? (I tried to use the get() method of shared_ptr but template deduction fails then) Or is there another way to assert for a whole container?
one more way to do it:
assert(std::find(pFoos.begin(), pFoos.end(), nullptr) == pFoos.end());
Another slightly convoluted way to express it with standard functionality only:
assert(std::none_of(pFoos.begin(), pFoos.end(), std::logical_not<std::shared_ptr<Foo>>{}));
From C++14 onwards, you can use the generic specialization of std::logical_not:
assert(std::none_of(pFoos.begin(), pFoos.end(), std::logical_not<>{}));
You could use implement your own utility predicate:
struct is_nullptr
{
template <typename T>
bool operator()(T&& x) const noexcept { return x == nullptr; }
};
void doSomething(const std::vector<std::shared_ptr<Foo> >& pFoos)
{
assert(!std::any_of(pFoos.begin(), pFoos.end(), is_nullptr{});
// ...
}
And/or your own "range assertion":
template <typename TContainer, typename TPredicate>
void range_assert(TContainer&& container, TPredicate&& p)
{
for(auto&& x : container)
{
assert(p(x));
}
}
void doSomething(const std::vector<std::shared_ptr<Foo> >& pFoos)
{
range_assert(pFoos, [](const std::shared_ptr<Foo>& x) { return x; });
// ...
}

Const converting std containers

Consider that I have a std::vector.
std::vector<int> blah;
blah.push_back(1);
blah.push_back(2);
I now want to pass the vector somewhere and disallow modifying the contents of the objects its contains while still allowing to modify the container when able:
// Acceptable use:
void call_something() {
std::vector<int> blah;
blah.push_back(1);
blah.push_back(2);
// Currently, compiler error because of mismatching types
something(blah);
}
void something(std::vector<const int>& blah)
{
// Auto translates to 'const int'
for ( auto& i : blah ) {
// User cannot modify i.
std::cout << i << std::endl;
}
blah.push_back(blah.size()); // This should be acceptable
blah.emplace_back(); // This should be acceptable
return;
}
// Unacceptable use:
void something_else(const std::vector<int>& blah)
{
// Because of const vector, auto translates to 'const int'
for ( auto& i : blah ) {
std::cout << i std::endl;
}
blah.push_back(blah.size()); // This will present an unacceptable compiler error.
blah.emplace_back(); // This will present an unacceptable compiler error.
return;
}
Is there an easy way to do this?
To enable the operations you wish to allow while preventing the others, you need to take a fine-grained approach to your function's interface. For example, if your calling code were to pass const iterators (begin and end) as well as a back inserter (or custom back emplacer functor), then exactly the subset of operations you showed would be possible.
template <class Iter, class F>
void something(Iter begin, Iter end, F&& append)
{
using value_type = typename std::iterator_traits<Iter>::value_type;
std::copy(begin, end, std::ostream_iterator<value_type>(std::cout, "\n"));
append(std::distance(begin, end));
append();
return;
}
That said I don't find your examples particularly compelling. Do you have a real scenario in which you must maintain mutable elements, pass a mutable container to a function, yet treat the passed elements as immutable?
There is no easy way to do this. One way would be to wrap a vector in a type that exposes only the functionality that you want to allow. For instance
template<typename T, typename A = std::allocator<T>>
struct vector_wrap
{
using iterator = typename std::vector<T, A>::const_iterator;
using const_iterator = typename std::vector<T, A>::const_iterator;
using size_type = typename std::vector<T, A>::size_type;
vector_wrap(std::vector<T, A>& vec)
: vec_(&vec)
{}
void push_back(T const& value) { vec_->push_back(value); }
void push_back(T&& value) { vec_->push_back(std::move(value)); }
size_type size() { return vec_->size(); }
iterator begin() const { return vec_->cbegin(); }
iterator end() const { return vec_->cend(); }
private:
std::vector<T, A> *vec_;
};
Since the above implementation only stores a pointer to the vector it wraps, you'll have to ensure that the lifetime of the vector is longer than that of vector_wrap.
You'll have to modify something and something_else so that they take a vector_wrap<int> as argument. Since vector_wrap::begin and vector_wrap::end return const_iterators, you'll not be allowed to modify existing elements within the for statement.
Live demo