Skip to content
Laviyx Learn

Try

Advanced C++ Practice

Practise lambdas, templates, exceptions, file streams, std::optional and move semantics in modern C++.

Advanced7 problemsUpdated

Review first: Lambdas, Templates, Exceptions, File Handling, Move Semantics and the Rule of Five, Modern C++ Features

  1. 1.Lambdas with captures

    Advanced

    Given std::vector<int> nums = {4, 11, 7, 20, 15, 2}; and int limit = 10;, use std::count_if with a lambda that captures limit to count the numbers above it. Then use std::for_each with a lambda that captures a total by reference to add up all the numbers.

    Show hint

    Capture by value with [limit] and by reference with [&total].

    Show solution
    C++
    #include <algorithm>
    #include <iostream>
    #include <vector>
    
    int main() {
        std::vector<int> nums = {4, 11, 7, 20, 15, 2};
        int limit = 10;
    
        auto above = std::count_if(nums.begin(), nums.end(), [limit](int n) { return n > limit; });
    
        int total = 0;
        std::for_each(nums.begin(), nums.end(), [&total](int n) { total += n; });
    
        std::cout << above << ' ' << total << '\n';
    }
    Output
    3 59
  2. 2.A function template

    Advanced

    Write a function template T largest(const std::vector<T>& v) that returns the largest element, and use it with {3, 9, 4}, {2.5, 1.5} and a vector of strings {"pear", "apple", "plum"}.

    Show hint

    template <typename T> before the function. Start from v[0] and compare with >.

    Show solution
    C++
    #include <iostream>
    #include <string>
    #include <vector>
    
    template <typename T>
    T largest(const std::vector<T>& v) {
        T best = v[0];
        for (const T& x : v) {
            if (x > best) best = x;
        }
        return best;
    }
    
    int main() {
        std::cout << largest(std::vector<int>{3, 9, 4}) << ' '
                  << largest(std::vector<double>{2.5, 1.5}) << ' '
                  << largest(std::vector<std::string>{"pear", "apple", "plum"}) << '\n';
    }
    Output
    9 2.5 plum

    Strings compare alphabetically, so "plum" is the largest of the three.

  3. 3.A class template

    Advanced

    Write template <typename K, typename V> struct Entry { K key; V value; }; and a function template print(const Entry<K, V>&) that prints key = value. Use it with Entry<std::string, int>{"age", 21} and Entry<char, double>{'x', 2.5}.

    Show hint

    The print function needs the same two template parameters: template <typename K, typename V>.

    Show solution
    C++
    #include <iostream>
    #include <string>
    
    template <typename K, typename V>
    struct Entry {
        K key;
        V value;
    };
    
    template <typename K, typename V>
    void print(const Entry<K, V>& e) {
        std::cout << e.key << " = " << e.value << '\n';
    }
    
    int main() {
        print(Entry<std::string, int>{"age", 21});
        print(Entry<char, double>{'x', 2.5});
    }
    Output
    age = 21
    x = 2.5
  4. 4.Handle bad input with exceptions

    Advanced

    For each of "42", "abc" and "99999999999", convert the text with std::stoi and print the number, or invalid for std::invalid_argument, or too large for std::out_of_range.

    Show hint

    std::stoi throws std::invalid_argument when there is no number, and std::out_of_range when the value does not fit in an int.

    Show solution
    C++
    #include <iostream>
    #include <stdexcept>
    #include <string>
    
    int main() {
        for (std::string text : {"42", "abc", "99999999999"}) {
            try {
                int value = std::stoi(text);
                std::cout << text << ": " << value << '\n';
            } catch (const std::invalid_argument&) {
                std::cout << text << ": invalid\n";
            } catch (const std::out_of_range&) {
                std::cout << text << ": too large\n";
            }
        }
    }
    Output
    42: 42
    abc: invalid
    99999999999: too large
  5. 5.Write and read a file

    Advanced

    Write three lines Asha 92, Ravi 85 and Meera 78 to scores.txt. Then read the file back with >> and print the name of the top scorer and the average score.

    Show hint

    Use std::ofstream to write and std::ifstream to read; while (in >> name >> score) reads pairs until the end.

    Show solution
    C++
    #include <fstream>
    #include <iostream>
    #include <string>
    
    int main() {
        {
            std::ofstream out("scores.txt");
            out << "Asha 92\nRavi 85\nMeera 78\n";
        }
    
        std::ifstream in("scores.txt");
        std::string name;
        int score = 0;
        std::string best_name;
        int best = -1;
        int total = 0;
        int count = 0;
    
        while (in >> name >> score) {
            total += score;
            ++count;
            if (score > best) {
                best = score;
                best_name = name;
            }
        }
        std::cout << best_name << ' ' << static_cast<double>(total) / count << '\n';
    }
    Output
    Asha 85
  6. 6.Return an optional

    Advanced

    Write std::optional<int> find_age(const std::map<std::string, int>& ages, const std::string& name) that returns the age or std::nullopt. Print the result for "Asha" and, using value_or(-1), for "John".

    Show hint

    Use ages.find(name) and compare with ages.end().

    Show solution
    C++
    #include <iostream>
    #include <map>
    #include <optional>
    #include <string>
    
    std::optional<int> find_age(const std::map<std::string, int>& ages, const std::string& name) {
        if (auto it = ages.find(name); it != ages.end()) {
            return it->second;
        }
        return std::nullopt;
    }
    
    int main() {
        std::map<std::string, int> ages = {{"Asha", 21}, {"Ravi", 25}};
    
        if (auto age = find_age(ages, "Asha")) {
            std::cout << "Asha is " << *age << '\n';
        }
        std::cout << find_age(ages, "John").value_or(-1) << '\n';
    }
    Output
    Asha is 21
    -1
  7. 7.Move instead of copy

    Advanced

    Create a std::vector<std::unique_ptr<std::string>> and add three heap-allocated strings to it. One of them is first created in a local unique_ptr and then moved in. Print the strings, and whether the local pointer is empty afterwards.

    Show hint

    A unique_ptr cannot be copied into the vector; use push_back(std::move(local)).

    Show solution
    C++
    #include <iostream>
    #include <memory>
    #include <string>
    #include <utility>
    #include <vector>
    
    int main() {
        std::vector<std::unique_ptr<std::string>> items;
        items.push_back(std::make_unique<std::string>("first"));
    
        auto local = std::make_unique<std::string>("second");
        items.push_back(std::move(local));
    
        items.push_back(std::make_unique<std::string>("third"));
    
        for (const auto& item : items) std::cout << *item << ' ';
        std::cout << '\n' << std::boolalpha << (local == nullptr) << '\n';
    }
    Output
    first second third
    true