Forum Replies Created
-
AuthorPosts
-
::
Move constructors typically “steal” the resources held by the argument, and leave the argument in some valid but otherwise indeterminate state.
You can study the move constructor by studying the corresponding implementation:
::Overloading the multiplication operator with a double from left and from right is the correct way to do it. You can automatically generate a few of the arithmetic operations with ugly CRTP tricks. For example, you can automatically generate a/b, b/a, a*b from b*a. Study the example crtpEquality.cpp.
I discuss this sophisticated technique in my mentoring program “Design Patterns and Architectural Patterns with C++“.
::The error message is misleading.
int main() { int i = 13; int j = 5; int* p = &i; // p = &j and *p = i works // int* const p = &i; => p = &j breaks // const int* p = &i => *p = i breaks }
When I make the pointer and the pointed-to element non-const, both assignment works. When I add constness to the pointer and the pointed-to element, one assignment will break.
::I argue from the perspective of a constexpr function, but you can also apply it to a constexpr user-defined type. There are essential three cases for a constexpr declared function func.
constexpr int func(int a) { return 2 * a; }
- func is used in context that requires compile-time execution:
- inside static_assert
- for a c-array initialization
- inside a constexpr function
- you want to have the result of func on compile time: constexpr auto res = func(5)
- func is invoked with a run-time argument => func(a) can only be executed at runtime
- func can either run at compile time or runtime; it’s essentially a question of the optimizer
::Usually, a compiler transforms copy initialization into direct initialization. The C++ standard say: “When certain criteria are met, an implementation is allowed to omit the copy construction of a class object …” .When I use the following program in Compiler Explorer without and with maximum optimization, I see a small difference with maximum optimization for a std::string but not for an int.
#include <iostream> #include <string> int main() { std::string s {"Hello"}; // (1) std::string s2 = "Hello"; // (2) std::cout << s << " " << s2; int a1{5}; int a2 = 5; std::cout << a1 << " " << a2; }
The copy initialization for the std::string s2 generates an additional assembler mov instruction (line 15). Compare the following screenshot of (1) and (2) in den example above:

Without optimization, I can neither observe a difference for a std::string or int.
Rule of thumb: prefer direct initialization
::Image, you want to sell cars. When your customer comes, you can decide, which car you want to assemble. You can even change a wheel of the car during runtime. You simply have to implement a member function changeWheel on the car.
virtual void changeWheel(std::unique_ptr<Wheel> wh) = 0;
By the way, this is an application of the strategy pattern or dependency injection. Both techniques are based on composition.
::This following program shows the issue.
#include <functional> #include <iostream> #include <string> std::function<std::string()> makeLambda() { const std::string val = "on stack created"; return [&val]{return val;}; } int main(){ auto bad = makeLambda(); std::cout << bad(); }
The local variable var goes out of scope. The program has undefined behavior. I will discuss this in more detail in week 9.
17. February 2023 at 09:58 in reply to: Finding out the type of a polymoprphic type without using dynamic_cast #461781::To put it together, this is your structure:
struct FileHandler{ virutual std::string Read() const = 0; virtual Write(std::string s) = 0; }; class DiskFile: public FileHandler { ... }; class MemoryFile: public FileHandler { ... }; void NeedFileHandler(FileHandler* fHandler) { // reads and writes }
After painting this picture, I understand your question. But there is some point, I don’t understand. In general, the correct place to check if an object is correctly created is the constructor. Consequentially, doing this validation step in the function is too late.
::I want to answer as a C++ trainer.
- In Germany, 60 % of my customers are car related. Most are car suppliers such as Continental, E-Solutions, or Bosch. In the last years, I have had around 15 classes for Bosch a year worldwide.
- 30 % of my customers are in the embedded domain – most of them in the medical area.
- The remaining 10 % of customers are mainly from the financial domain.
When I give classes outside Germany, the relations change. The car manufacturer and suppliers are not so dominant.
::Exactly. I will present the concurrency pattern in the “Design Patterns in Architectural Patterns with C++” mentoring program (weeks 14 – 16). In this mentoring program, I explain only the techniques. In particular, I will present Strategized Locking, Scoped Locking, and the Thread-Safe Interface, to only name a few.
::void setTrue(){ while(counter <= COUNTLIMIT){ std::unique_lock<std::mutex> lck(mutex_); condVar1.wait(lck, []{return dataReady == false;}); dataReady= true; ++counter; std::cout << dataReady << '\n'; condVar2.notify_one(); } }
You have to distinguish two cases:
The call condVar1.wait(lck, []{return dataReady == false;}); is
- Not successful: unlocks the mutex and puts the thread in a blocked state
- Successful: The mutex is still locked until the lck goes out of scope. The std::unique_lock lck is responsible for unlocking the mutex.
This means that the mutex cannot be acquired two times in a row.
::Here is the short answer: To make it short. When you use mutexex, use a std::scoped_lock.
And here is, why:
std::lock (C++11) and std::scoped_lock (C++17). Both lock their underlying objects, but here is the difference:
- std::lock locks only it’s underlying lock-like type. std::lock is no owner. Consequentially, you invoke std::lock with an owner such as std::unique_lock.
- std::scoped_lock is an owner modelling RAII. It locks in mutex-like type in its constructor and unlocks it in its destructor.
Referring to your example. std::lock only locks but not unlock its mutex. To see the difference, I add the unlock class manually: https://godbolt.org/z/K4M6vnfWd
- func is used in context that requires compile-time execution:
-
AuthorPosts
