text: /*
   * Copyright (c) 2018
   *
   * Permission is hereby granted, free of charge, to any person obtaining a copy of
   * this software and associated documentation files (the "Software"), to deal in
   * the Software without restriction, including without limitation the rights to
   * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
   * the Software, and to permit persons to whom the Software is furnished to do so,
   * subject to the following conditions:
   *
   * The above copyright notice and this permission notice shall be included in all
   * copies or substantial portions of the Software.
   *
   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
   * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
   * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
   * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
   * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
   */
  
  // Ref : http://en.cppreference.com/w/cpp/utility/optional
  #include <string>
  #include <functional>
  #include <iostream>
  #include <optional>
  #include <cstdlib>
  #include <ctime>
   
  // optional can be used as the return type of a factory that may fail
  std::optional<std::string> create(bool b) {
      if (b)
          return "Godzilla";
      return {};
  }
   
  // std::nullopt can be used to create any (empty) std::optional
  auto create2(bool b) {
      return b ? std::optional<std::string>{"Godzilla"} : std::nullopt;
  }
   
  // std::reference_wrapper may be used to return a reference
  auto create_ref(bool b) {
      static std::string value = "Godzilla";
      return b ? std::optional<std::reference_wrapper<std::string>>{value}
               : std::nullopt;
  }
  
  auto rand_create(int x){
  	return ( (x * std::rand()) % 2) ? std::optional<std::string>{"Odd Number"} : std::nullopt;
  }
   
  int main()
  {
  	std::srand(std::time(0));
      std::cout << "create(false) returned "
                << create(false).value_or("empty") << '\n';
   
      // optional-returning factory functions are usable as conditions of while and if
      if (auto str = create2(true)) {
          std::cout << "create2(true) returned " << *str << '\n';
      }
   
      if (auto str = create_ref(true)) {
          // using get() to access the reference_wrapper's value
          std::cout << "create_ref(true) returned " << str->get() << '\n';
          str->get() = "Mothra";
          std::cout << "modifying it changed it to " << str->get() << '\n';
      }
  
  	std::vector<int> v{0, 1, 2, 3, 4, 5};	
  	std::for_each(v.begin(),v.end(),[](const int& n){std::cout << "rand_create() returned " << rand_create(n).value_or("empty") << "\n";});
  }
  