Category Archives: C++
static_cast can’t convert from a virtual base class in C++
It converts only from non-virtual base class subobject:
struct B
{
virtual ~B() {};
};
struct D : public virtual B { };
int main()
{
D d;
B& br1 = d;
// cannot convert a 'B*' to a 'D*'; conversion from a virtual base class is implied
// static_cast<D&>(br1);
dynamic_cast<D&>(br1);
return 0;
}
Storage duration and linkage in C++
In the vernacular they say stack and heap, but the standard call this automatic and dynamic:
(more…)How we use forwarding references with ranges in C++
The parameter or print
function is a forwarding reference because the range can change while being iterated, but the current value is l-value reference:
#include <string>
#include <vector>
#include <ranges>
#include <iostream>
template <class R, class Value>
concept range_over = std::ranges::range<R> &&
std::same_as<std::ranges::range_value_t<R>, Value>;
template <range_over<std::string> Range>
void print(Range&& range)
{
for (const std::string& val : range)
{
std::cout << val << std::endl;
}
}
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;
}
}
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;
}
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.
(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
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';
}
}
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.