Example

// unique algorithm example
#include <iostream>     // std::cout
#include <algorithm>    // std::unique, std::distance
#include <vector>       // std::vector


int main () {
  int myints[] = {10,20,20,20,30,30,20,20,10};           // 10 20 20 20 30 30 20 20 10
  std::vector<int> myvector (myints,myints+9);

  // using default comparison:
  std::vector<int>::iterator it;
  it = std::unique (myvector.begin(), myvector.end());   // 10 20 30 20 10 ?  ?  ?  ?
                                                         //                ^
  // print out content:
  std::cout << "myvector contains:";
  for (it=myvector.begin(); it!=myvector.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';

  std::sort(myvector.begin(), myvector.end()); // 10 10 20 20 30 
  // print out content:
  std::cout << "myvector contains:";
  for (it=myvector.begin(); it!=myvector.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';
  
  myvector.erase(std::unique(myvector.begin(), myvector.end()), myvector.end());; // 10 20 30
  
  // print out content:
  std::cout << "myvector contains:";
  for (it=myvector.begin(); it!=myvector.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';

  return 0;
}

resize()

void resize (size_type n);
void resize (size_type n, const value_type& val);

Resizes the container so that it contains n elements.

If n is smaller than the current container size, the content is reduced to its first n elements, removing those beyond (and destroying them).

If n is greater than the current container size, the content is expanded by inserting at the end as many elements as needed to reach a size of n. If val is specified, the new elements are initialized as copies of val, otherwise, they are value-initialized.

If n is also greater than the current container capacity, an automatic reallocation of the allocated storage space takes place.

Notice that this function changes the actual content of the container by inserting or erasing elements from it.

Example

// resizing vector
#include <iostream>
#include <vector>

int main ()
{
  std::vector<int> myvector;

  // set some initial content:
  for (int i=1;i<10;i++) myvector.push_back(i);

  myvector.resize(5);
  myvector.resize(8,100);
  myvector.resize(12);

  std::cout << "myvector contains:";
  for (int i=0;i<myvector.size();i++)
    std::cout << ' ' << myvector[i];
  std::cout << '\n';

  return 0;
}
  • Output myvector contains: 1 2 3 4 5 100 100 100 0 0 0 0

boost::optional

  • Class template optional is a wrapper for representing ‘optional’ (or ‘nullable’) objects who may not (yet) contain a valid value.
  • Introduced and supported from C++17 in std::optional (defined in header <optional>)
  • Supported in code by including #include <boost/optional.hpp>

    It is recommended to use optional in situations where there is exactly one, clear (to all parties) reason for having no value of type T, and where the lack of value is as natural as having any regular value of T.

  • Empty return data value
#include<iostream>
#include<fstream>

std::string ReadFileAsString(const std::string& filepath) {
    std::ifstream stream(filepath);
    if(stream) {
        std::string res;
        //read file
        stream.close();
        return res;
    }
    return std::string(); // return ""; --> empty string
}
int main() {
    std::string data = ReadFileAsString("data.txt");
    if(data != "") // 
    {

    }
}
  • Utilize optional to deal with no value data
#include<iostream>
#include<fstream>
#include<optional> //introduced in c++17

std::optional<std::string> ReadFileAsString(const std::string& filepath) {
    std::ifstream stream(filepath);
    if(stream) {
        std::string res;
        //read file
        stream.close();
        return res;
    }
    return {}; // return ""; --> empty string
}
int main() {
    std::optional<std::string> data = ReadFileAsString("data.txt");

    std::string value = data.value_or("Not present");
    if(data.has_value()) //if(data) --> is okay
    {
        //optional has been set
        cout << data.value();
    }
    else 
    {
        //optional has not been set
    }
}
  • value_or
    • if the data is present, it will return to us the value
    • if the data is not set, it will return whatever value parsed in HERE.
      • value_or(“HERE”);
      • usually default value is set in HERE

boost::make_optionl

optional<T (not a ref)> make_optional( T const& v )
optional<T (not a ref)> make_optional( bool condition, T const& v )
  • Returns: optional(v) for the deduced type T of v.
  • Returns: optional(condition,v) for the deduced type T of v.

  • Example 1
    • when using make_optional - can utilize condition
    • Creates an optional initialized with 'val' IFF cond is true, otherwise creates an `uninitialized optional`
#include "boost/optional/optional.hpp" // boost/none.hpp is included automatically

boost::optional<int> foo ( int a )
{
  return some_condition(a) ? boost::make_optional(a) : boost::none ; 
  // NOTE: in real code you can just use this: make_optional(some_condition(a), a) 
}
  • defined code
typedef optional_detail::optional_base<T> base ;
// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialzed optional<T>.
// Can throw if T::T(T const&) does
optional_base ( bool cond, argument_type val )
  :
  m_initialized(false)
{
  if ( cond )
    construct(val);
}

// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
// Can throw if T::T(T const&) does
optional ( bool cond, argument_type val ) : base(cond,val) {}


// Returns optional<T>(cond,v)
template<class T>
inline
optional<T> make_optional ( bool cond, T const& v )
{
  return optional<T>(cond,v);
}

uninitialized optional

  • uninitialized optional
    • In C++ there is no formal notion of uninitialized objects, which means that objects always have an initial value even if indeterminate. As discussed on the previous section, this has a drawback because you need additional information to tell if an object has been effectively initialized. One of the typical ways in which this has been historically dealt with is via a special value: EOF,npos,-1, etc… This is equivalent to adding the special value to the set of possible values of a given type.
    • when a variable is declared as optional and no initial value is given, the variable is formally uninitialized. A formally uninitialized optional object has conceptually no value at all and this situation can be tested at runtime. It is formally undefined behavior to try to access the value of an uninitialized optional. An uninitialized optional can be assigned a value, in which case its initialization state changes to initialized. Furthermore, given the formal treatment of initialization states in optional objects, it is even possible to reset an optional to uninitialized.

      boost::none

namespace boost {
class none_t {/* see below */};
const none_t none (/* see below */);
} // namespace boost

optional supports uninitialized states with a convenient syntax via a constant of the implementation-defined type `boost::none_t`, identified as boost::none.

Starting with Boost version 1.34.0, both boost::none_t and boost::none are included in boost/none.hpp, which is automatically included by boost/optional/optional.hpp

This contant is similar in purpose to NULL, except that is not a null pointer value. You can use it to initialize an optional instance, which has the same effect of a default constructor, and you can assign it which has the effect of reseting the optional instance. You can also use it in relational operators to make the predicate expression more clear.