Category Archives: C++

Value category is a property of an expression in C++ or std::forward explained

The code below prints l-value:

#include <iostream>

namespace
{
    void foo(const int&)
    {
        std::cout << "const l-value" << std::endl;
    }

    void foo(int&)
    {
        std::cout << "l-value" << std::endl;
    }

    void foo(int&&)
    {
        std::cout << "r-value" << std::endl;
    }
}
(more…)

The right way to capture std::unique_ptr into a lambda expression

Starting from C++14:

#include <string>
#include <memory>

int main()
{
    std::unique_ptr<std::string> p = std::make_unique<std::string>("abc");

    auto func = [p = std::move(p)]()
    {
    };

    func();

    return 0;
}
(more…)

MSVC 2022 compiler bug

Static asserts in the code below do not fail with MSVC 19.32.31332 for x86:

#include <string>

int main()
{
    std::string v = "abc";

    auto func = [v]()
    {
        auto& l_ref = v;

        static_assert(std::is_same_v<decltype(l_ref), std::string&>);

        auto&& r_ref = std::move(v);

        static_assert(std::is_same_v<decltype(r_ref), std::string&&>);
    };

    func();

    return 0;
}

that is MSVC compiler bug. With GCC both l_ref and r_ref are const references.

Thanks to stackoverflow.com.

Reported this to Microsoft.

(more…)

An example of how r-value reference works in C++

An example of extending the lifetime of a temporary:

#include <iostream>

int main()
{
    int a = 1;
    int&& b = std::move(a);
    int&& c = b + 1;

    b = b + 1;
    c = c + 1;

    std::cout << a << b << c;
}

The output is:

223
(more…)

Using std::future as a coroutine in C++20

In C++20 it is possible to do this:

std::future<int> compute(as_coroutine) {
  int a = co_await std::async([] { return 6; });
  int b = co_await std::async([] { return 7; });
  co_return a * b;
}
 
std::future<void> fail(as_coroutine) {
  throw std::runtime_error("bleah");
  co_return;
}
 
int main() {
  std::cout << compute({}).get() << '\n';
 
  try {
    fail({}).get();
  } catch (const std::runtime_error &e) {
    std::cout << "error: " << e.what() << '\n';
  }
}
(more…)

Waitable QTimer with C++20 coroutines

Found an example of overriding co_await operator and was able to implement my own version:

#include <QTimer>
#include <QMetaObject>

#include <chrono>
#include <coroutine>

//QTimer accepts only milliseconds.
class TimeAwaitable
{
public:

    explicit TimeAwaitable(std::chrono::milliseconds d) : m_d(d) {}

    ~TimeAwaitable()
    {
        if (m_connection)
        {
            QObject::disconnect(m_connection);
        }
    }

    bool await_ready() const noexcept
    {
        return m_d <= std::chrono::milliseconds(0);
    }

    void await_suspend(std::coroutine_handle<> h) noexcept
    {
        m_connection = QObject::connect(&m_timer, &QTimer::timeout,
            [this, h]()
            {
                QObject::disconnect(m_connection);

                h.resume();
            });

        m_timer.setSingleShot(true);
        m_timer.start(m_d);
    }

    void await_resume() const noexcept {}

private:

    std::chrono::milliseconds m_d;
        
    QTimer m_timer;

    QMetaObject::Connection m_connection;
};

inline TimeAwaitable operator co_await(std::chrono::milliseconds d) noexcept
{
    return TimeAwaitable{ d };
}

For those who did not work with QT, QTimer::singleShot simply calls the lambda on the current thread after a given interval.

(more…)

Did you already learn what are C++ concepts?

In C++20 we can do this:

#include <ranges>
#include <vector>

template <std::ranges::range Range>
    requires std::same_as<std::ranges::range_value_t<Range>, int>
auto TransformIt(Range r)
{
    return r | std::views::transform([](int n) { return n * n; });
}

int main()
{
    std::vector<int> v;
    auto r = TransformIt(v);
    return 0;
}
(more…)

std::unique_ptr with a deleter that throws an exception

The program below is terminated when the deleter throws the exception:

#include <iostream>
#include <memory>

struct X
{
    int value;
};

struct Deleter
{
    void operator()(X* p) noexcept(false)
    {
        if (p->value == 0)
        {
            throw std::logic_error("Can't delete a zero.");
        }

        delete p;
    }
};
(more…)

An example of heterogeneous lookup with std::unordered_set in C++20

std::unordered_set has a template find function in C++20. To make it work I define a custom hash and a custom equality compares as follows:

struct BotSettings
{
    std::string type;
    std::string name;
    bool started;
};
(more…)

Array subscript -N is outside array bounds warning in GCC11

Consider the code below with UB:

template <class Derived>
class A
{
public:

    Derived * get() { return static_cast<Derived *>(this);}

private:

    int m_a;
};

class B
{
public:

    double m_b;
};

class X : public B, public A<X>
{
public:

    int m_x;
};

int main()
{
    A<X> a;
    std::cout << a.get();
    return 0;
}
(more…)