Skip to content

C++ Gurus

The forum for all discussions in C++ land.
1.3k Topics 8.4k Posts
  • The Question of a Lifetime

    Unsolved
    4
    0 Votes
    4 Posts
    70 Views
    S

    It might work right now, but will not in the future.

    There is a new feature coming to C++26 (https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2795r3.html) which addresses a problem related to this. Currently if you do something like this

    void f() { const char password[] = "secret"; } void g() { char str[7]; std::cout << str << '\n'; } int main() { f(); g(); }

    it will most likely print secret. Both functions will use the same stack space and reuse the same memory. The proposal for C++26 is to handle uninitialized variables explicitly to avoid this problem.

    On the other hand this also means in your concrete case if some other function reuses the same stack space it will overwrite \x11\x01\x1E\xD0.

    Someone should check the following with the standard, but I believe there is a difference between

    char serialNumberCommand[] = "\x11\x01\x1E\xD0";

    and

    char *serialNumberCommand = "\x11\x01\x1E\xD0";

    I would expect the first version to copy the string into the serialNumberCommand array. In the latter case you are just holding a pointer to an existing string in static storage. This pointer can then be handed safely to QByteArray::fromRawData as QByteArray will not hold the pointer handed to it, but the thing it points to. The thing it points to should be permanent. (I am not sure it the C++ standard guarantees this, but it is the general implementation of C strings.)

    If you want something more fancy, there is not only constexpr but also constinit (since C++20). cppreference (https://en.cppreference.com/w/cpp/language/constinit) mentions that constinit declares a variable with static or thread storage duration. However, as the example on that page shows, you need to write static constinit inside a function. Just constinit alone will not do.

  • Unable to create C++ google test for the C++ class

    Unsolved
    4
    0 Votes
    4 Posts
    116 Views
    Christian EhrlicherC

    @Bharath-kumar said in Unable to create C++ google test for the C++ class:

    But here I am stuck how and where should I create QApplication object.

    Before you create any widget.

  • To singleton or not to singleton, that is the question....

    Solved
    23
    0 Votes
    23 Posts
    709 Views
    S

    @JoeCFD said in To singleton or not to singleton, that is the question....:

    Calling baz() with using "using Foo;" can cause confusing while two namespaces are present at the same place.

    In the concrete example you have given, it would not compile because the compiler cannot resolve the overload (i.e. Foo1::baz or Foo2::baz). You'd still need to use a fully qualified name. It only gets confusing when you have Foo1::baz(int) and Foo2::baz(double). You might write baz(1); when you actually want to call Foo2::baz. The software might even do the right thing for years. Someone might just introduce Foo1::baz years down the line and suddenly the behavior changes.

  • Template class as parameter question

    Solved
    6
    0 Votes
    6 Posts
    149 Views
    S

    @JonB said in Template class as parameter question:

    What happens when another container has a different definition of count() which does not return an int (or number)? Maybe your syntax is not quite correct and it would have to be requires(T t) { int t.count(); }?

    I guess this would be some additional requirement using std::is_same_v and decltype(t.count()). I'm still on C++17, so I haven't used concepts myself.

    @JonB said in Template class as parameter question:

    Hmph! But that's is just what e.g. QList is, and loads of other containers.

    A container class is an obvious example where a general purpose implementation makes sense. But, you usually don't implement your own containers. Furthermore, most of the time I would have at least int and double in mind for containers. So, making them general purpose from the get go is a given. But, I don't have to make all my algorithms general purpose such that they might be reusable decades down the line if ever. If there is a current need for general purpose code, make it general purpose. Otherwise it just make maintenance more complicated while being unnecessary. I guess it might also introduce additional bugs because you try to be extra clever.

  • Subclassing where parent class has `[]` operator

    Unsolved
    11
    0 Votes
    11 Posts
    268 Views
    S

    Well, first of all (user-defined) operators in C++ are just functions. Hence, it means you can call them using the function syntax (like mentioned as operator[](someIndex)). To understand why you cannot just write [someIndex] we need to look at the history of C++; or rather C. We get the index operator syntax from plain arrays and pointers. These require the array or pointer to be explicitly written before the operator: p[i] or array[i]. (To be more precise: These are the same as i[p] and i[array] because officially in C these are equivalent to p+i=i+p and array+i=i+array. However, this weird syntax does not work for operator[] overloading and doesn't help to make my point.) In the same way you need to write the object on which to call the overloaded operator[] in front of the index access. If you could use implicit this, the same would need to apply e.g. for the binary operator+ and the like. What about operator=? I personally also think that just [someIndex] is not really readable. It doesn't show directly that you want to use an index operator. I prefer that you must write (*this)[someIndex] explicitly. In most places I would use it like this. Only when I want to make plain that I want to forward to operator[] (as was initially asked) I would make the forwarding aspect clear by writing operator[](someIndex).

    Furthermore, now it is too late to introduce the short-hand syntax (implicit this) into C++. [] without an object preceeding it is already reserved for introducing lambdas. I would expect that the compiler error for return [someIndex]; would say something along the lines that the body for the lambda function is missing. (return [someIndex]{}; would return a lambda that does nothing, but captures someIndex by value. Function arguments () are optional for lambdas if they are empty.)

    Sometimes when I need to use some operators (not necessarily the index operator) several times inside a member function (and I'm annoyed at writing (*this) over and over again) I would write auto &self = *this;. Then, it is much nicer to write return self[someIndex];. (The name self is derived from other OO languages that use a reference self to the object instead of a pointer this.)

  • SIGNAL/SLOT() macros in Qt's source code

    Solved
    19
    0 Votes
    19 Posts
    426 Views
    SGaistS

    @GrecKo said in SIGNAL/SLOT() macros in Qt's source code:

    @Pl45m4 said in SIGNAL/SLOT() macros in Qt's source code:

    The string-based connection does not need QObject receiver.

    The signature is QObject::connect(const QObject *, const char *, const QObject *, const char *, Qt::ConnectionType ) though

    This was referring to this overload:

    QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal, const char *method, Qt::ConnectionType type = Qt::AutoConnection) const

    Which implies that the target is the current object.

    This is different from the similar (yet different) PMF variant as there's no implicit target in that case. Hence the recommendation to use the variant which has a context object.

  • QList need to know all modifications

    Unsolved
    18
    0 Votes
    18 Posts
    558 Views
    S

    Each class has its own vtable (it is not per object). Each object then has a pointer to the vtable. When you have a pointer to a base class pointing to an object of a derived class, it just uses the pointer to the vtable and calls the appropriate function. Like mentioned before, this is only one indirection. (It gets more complicated with multiple inheritance.)

    Concerning Objective-C: Most strings for message are compile-time known strings. This means that "string comparison" in reality is most of the time just comparison of pointers. The runtime also uses a little cache to speed up the most recent function calls.

    BTW: Since we are always talking about performance here. There is a CppCon talk on Youtube "Optimizing Away C++ Virtual Functions May be Pointless" https://youtu.be/i5MAXAxp_Tw?si=ieyiW3G31UMmANV-

  • QObject-inherited classes' virtual destructor method

    Solved
    8
    0 Votes
    8 Posts
    179 Views
    JonBJ

    @J-Hilk
    Yes, as you say, it comes from UI app. I often pick the UI template for a test project so I get the QApplication and necessary Makefile/cmake stuff but then uncheck the "create .ui file" box as I don't want that and create widgets in code. Which leaves me with the empty destructor code. I am now happy that I don't need that unless I want it.

  • Algorithm: finding the number contained within most intervals

    Unsolved
    13
    0 Votes
    13 Posts
    621 Views
    S

    Here is another idea: Treat the intervals as sets and compute their intersections.

    Start with the first interval and compute the intersection with every other interval. Store the intersections inside a second vector. The second vector should now have n-1 elements (intersection of 1st with 2nd, 1st with 3rd, 1st with 4th, ..., 1st with nth, but not 1st with 1st). Now you take the intervals in this second vector and intersect them with all original intervals again (first interval in the second vector is for 1st with 2nd, so we only need to start intersecting starting from 3rd, for the second interval we start from the 4th interval, and so on). The intersections are then stored inside a third vector. If there are only empty intervals inside the third vector, we can stop for now. Otherwise we throw away the second vector and repeat this process with the third vector. (The second vector is intersections containing 2 intervals, the third vector contains intersections of 3 intervals, so we don't need the second vector anymore if there are non-empty intervals in the third vector.) From the last vector we get from this process we keep one intersected interval (just take the first non-empty intersection) and remember it. It is the intersection with the most intervals including the first interval. Now, we repeat this for the second interval, and so on.

    This should give as for each interval the maximum of intersections containing this interval and the interval limits of the intersection. You can just pick the intersected interval with the highest number of intersections and use the minimum of that interval as the number.

    It is a little tricky to wrap your head around this (initially I thought it would be little easier). The way I described it runtime would be at least O(n³). I'm not sure if this is good or bad.

  • 0 Votes
    2 Posts
    122 Views
    J

    Never Mind, turns out there was a bug elsewhere in my code. Both methods work lol. I should really call it a day...

  • 0 Votes
    2 Posts
    126 Views
    SGaistS

    Hi,

    If you want to to mock QSerialPort you have to make it replaceable in your class.
    Use a QIODevice pointer as member and either add a setter or a constructor parameter so you can use either QSerialPort or your own mock device.
    This means that you need to refactor your logic a bit to setup the port.
    On a side note, your class has two different things that look suspicious:

    It seems to be doing way too many things seeing its internal and the class name singleton implementation more often than not are architectural issues.
  • Qt6 C++ compilation changes

    Unsolved
    17
    0 Votes
    17 Posts
    851 Views
    JoeCFDJ

    @JonB We learn more from discussions. I do not feel you are difficult in any way.

  • Qt Creator Code Model error on legal attribute

    Solved
    11
    0 Votes
    11 Posts
    466 Views
    JonBJ

    UPDATE/CORRECTION

    I tried again with switching Use clangd on and off. Somehow it seems it didn't "take" right formerly. Now I do see different behaviour. I find that sometimes when I start Creator, it warns me I have don't have enough memory for clangd, I selected "Enable anyway", it still red-underlines [[fallthrough]];. Then I go to Preferences, switch off clangd and then switch it back on, that clears the complaint. It seems I have to switch off and back on every time to make it work. Sigh....

    With clangd switched on I can use any of the [[fallthrough]]; annotations which get through gcc compiler and code editor does not red underline them. Q_FALLTHROUGH() macro still requires a blank line without clangd, but works without blank line with clangd. Fair enough, @aha_1980 has warned me that it will be "problematic* with the internal code model rather than clangd.

    So all in all I can now use [[fallthrough]]; in my code with clangd, that is apparently "standard" C++ 17 so I accept that.

  • Qt6 linking change

    Solved
    3
    0 Votes
    3 Posts
    201 Views
    JonBJ

    @SimonSchroeder Thanks, that's great to know. Marking yours as solution.

  • templated parameter packs

    Unsolved
    1
    0 Votes
    1 Posts
    105 Views
    No one has replied
  • How to run Unit Test and main project ?

    Solved
    7
    0 Votes
    7 Posts
    288 Views
    SGaistS

    Hi,

    The best way to do it is to create a subdirs project as described here. Even though it shows it for an application with libraries, the same concept applies to adding tests. You can check the Qt 5 sources, they are using that concept there.

  • 0 Votes
    2 Posts
    154 Views
    sierdzioS

    Doxygen is a good choice, I don't know if it will fit your requirements exactly though. It can show nice class-subclass hierarchies if you enable dot diagrams. In cmake this can be done like so:

    find_package(Doxygen REQUIRED dot)

    (https://www.doxygen.nl/manual/diagrams.html)

    This will result in something like this: https://www.doxygen.nl/manual/examples/diagrams/html/class_c.html

  • how to stop copy of a large file

    Unsolved
    7
    0 Votes
    7 Posts
    376 Views
    Kent-DorfmanK

    FWIW, since you are using the STL streams classes, note that you have buffer size control in the STL classes. One could weakly argue that you should use the Qt file IO methods instead of STL streams, since mixing frameworks is often the cause of problems in programming.

  • 2 Votes
    17 Posts
    851 Views
    JonBJ

    @Pl45m4
    I am now good on the algorithm. The one I am using (via @J-Hilk/ChatGPT) gives me a satisfactory answer I can work with and place my objects.

  • Some C++ questions about using <random>

    Unsolved
    8
    0 Votes
    8 Posts
    422 Views
    JonBJ

    @SimonSchroeder
    Sorry, but I don't think any part of my questions relate to random numbers or generators or distribution/uniformity performance. They are questions about C++ (especially the as-yet-unanswered question #3). With regard to the static-ness/number of times to call the initial "seeding" when comes with std::random_device rd; std::mt19937 gen(rd()); I only wish to reseed once and then accept the random number which comes from that, as is standard practice with random number generators (e.g. for old-style rand() we used to call srand() just once).