using std::swap instead of assignment with '=' operator - c++

I was going over some C++ source code from a library related to a pet-project I'm working on and encountered something I don't understand. In a place where I expected a pointer dereference followed by assignment, the library authors use std::swap() near the end of the function to write the result:
std::swap(*out, result);
I expected to see something like this:
*out = result;
Note that result is a typedef of size_t and out is a pointer to that same type.
When it comes to "systems programming", my background is in C and C# but not much at all in C++. Is there any particular reason for this type of "assignment"?

When the value types are more interesting, say, a std::vector<T>, for example, it may make more sense to std::swap() a temporarily constructed object into place rather than assigning it: given that the temporary result is about to go away, avoiding an assignment and just changing pointers makes some sense. I don't see any reason to do something like that with fundamental types like std::size_t, though.

Related

Why is there no overload for printing `std::byte`?

The following code does not compile in C++20
#include <iostream>
#include <cstddef>
int main(){
std::byte b {65};
std::cout<<"byte: "<<b<<'\n';// Missing overload
}
When std::byte was added in C++17, why was there no corresponding operator<< overloading for printing it? I can maybe understand the choice of not printing containers, but why not std::byte? It tries to act as primitive type and we even have overloads for std::string, the recent std::string_view, and perhaps the most related std::complex, and std::bitset itself can be printed.
There are also std::hex and similar modifiers, so printing 0-255 by default should not be an issue.
Was this just oversight? What about operator>>, std::bitset has it and it is not trivial at all.
EDIT: Found out even std::bitset can be printed.
From the paper on std::byte (P0298R3): (emphasis mine)
Design Decisions
std::byte is not an integer and not a character
The key motivation here is to make byte a distinct type – to improve program safety by leveraging the type system. This leads to the design that std::byte is not an integer type, nor a character type. It is a distinct
type for accessing the bits that ultimately make up object storage.
As such, it is not required to be implicitly convertible/interpreted to be either a char or any integral type whatsoever and hence cannot be printed using std::cout unless explicitly cast to the required type.
Furthermore, this question might help.
std::byte is intended for accessing raw data. To allow me to replace that damn uint8_t sprinkled all over the codebase with something that actually says "this is raw and unparsed", instead of something that could be misunderstood as a C string.
To underline: std::byte doesn't "try to be a primitive", it represents something even less - raw data.
That it's implemented like this is mostly a quirk of C++ and compiler implementations (layout rules for "primitive" types are much simpler than for a struct or a class).
This kind of thing is mostly found in low level code where, honestly, printing shouldn't be used. Isn't possible sometimes.
My use case, for example, is receiving raw bytes over I2C (or RS485) and parsing them into frame which is then put into a struct. Why would I want to serialize raw bytes over actual data? Data I will have access to almost immediately?
To sum up this somewhat ranty answer, providing operator overloads for std::byte to work with iostream goes against the intent of this type.
And expressing intent in code as much as possible is one of important principles in modern programming.

Error with std::bind and templated member functions

I am currently writing a gameboy emulator for practicing C++. I have gotten to the part where I implement CPU instructions and decided a vector of std::function was a good choice.
Please note: u8 is an alias for uint8_t.
In my code, there is a vector of std::function<u8()> with three types of members:
A lambda expression that returns u8.
Pointer to a member function.
Pointer to a templated member function.
I tried to use an initalizer list at first, but it didn't work. I later found out that is because I needed a call to std::bind(/*function ptr*/, this); on the pointers, but when calling this on the templated function pointers, I get the following error: no matching function for call to 'bind'. I would like to have an initalizer list, as right now it is a function with successive calls to emplace_back.
Here is the erroring line:
instruction_set.emplace_back(bind(&CPU::OPLoadDualRegister8<B, B>, this)); // 0x40 LD B, B
One interesting thing is that when B is replaced with a literal (e.g. 0x00) it works perfectly. B is a u8 and that is what the template accepts.
So:
Is there any way I can do this less convoluted? (e.g. init lists, std::function with member function ptrs, etc.)
If this is the best way, what do I do about the templated ptrs?
Would it better if I took the template params as args and used std::bind to resolve them (all params are either u8 or u8&.
Any optimization suggestions?
Thanks, Zach.
Okay, there is a lot going on here between your question and the comments. Here are some things I notice right off the bat:
If you are going to index into a vector to decode op codes, you probably shouldn't just emplace_back into the vector in order. Instead grow the vector to its final size, filling it with null values and use the subscript operator to put the functions in. instruction_set[0x40] = ...
Using a switch statement and just calling the functions directly is likely a way better choice. Obviously, don't know the ins and outs of your project, so this may not be possible.
When you say B is u8 do you mean B is variable of type u8? Plain 'ol variables can't be used to instantiate templates. B would have to be a macro, template parameter on the calling function, constexpr variable, or static const (basically known at compile time).
std::bind is never any fun for anyone to use, so you are not alone. I don't think it is the root cause of your issue here, but you should probably prefer binding things using capturing lambdas.
Funnily enough C++'s new hearthrob Matt Godbolt (author of Compiler Explorer) gave a talk on emulating a 6502 in JavaScript last year. It's not exactly an authoritative reference on the subject, but it may be worth a watch if you are interested in emulating old microprocessors.

What is wrong with my syntax in this 1 line bit of code (pointers and references and dereferences oh my)?

The code that I am having trouble with is this line:
result.addElement(&(*(setArray[i]) + *(rhs.setArray[j])));
The + operator in my class is overloaded like this (there are a variety of overloads that can fit in this set, but they all have a similar header):
const Rational Rational::operator+(const Rational &rhs) const
The setarrays in the code above are both arrays of pointers, but the + operator requires references, which might be the problem.
AddElement, the method of result, has this header:
bool Set::addElement(Multinumber* newElement)
The Multinumber* in the header is the parent class of Rational, mentioned above. I don't think any of the specific code matters. I'm pretty sure that it is a syntax issue.
My compiler error is:
68: error: invalid conversion from 'const Multinumber*' to 'Multinumber*'
Thank you for your help!
the issue is with const
bool Set::addElement(Multinumber* newElement) should be Set::addElement(const Multinumber* newElement)
Your operator + returns a const object. However, addElement requires a non-const object, which is where your compiler error is coming from. Basically, addElement is telling you that it feels at liberty to modify your Multinumber at will, but the operator + is beginning you not to modify the returned value.
You should just return a non-const object, unless there's a good reason not to. You're not returning a reference after all.
Of course, if the data in your Set is supposed to be constant and will never be changed, you may as well make addElement take a const pointer, and make sure that it internally deals with const pointers EVERYWHERE.
The issue is with the addElement expecting a non-const where as operator+ is returning a const object.
The fix for the code is cast the return as mentioned below
addElement((Multinumber * )&( *(setArray[i]) + *(rhs.setArray[j])));
If you dont want to cast, as casting might defeat the purpose of type checking here, then you have to change the signature of the addElement. That depending upon your project scope may have impact else where and if this API is public and other developers are using it. Changing signature will impact them also.
So choose wisely.
This code has much more serious issues than you can fix by adding a const or a typecast somewhere.
The result of this code will ultimately be a crash somewhere down the line, because you're passing a pointer to a temporary. Once you finish with line of code that calls addElement, the pointer will be left dangling, and trying to use the object it points to will either result in nonsense (if you're reading the object) or stack corrpution (if you're writing to the object).
The best way to redefine your code would be to change this to
bool Set::addElement(Multinumber newElement) //pass the Multinumber by value
and call addElement as follows:
result.addElement(*setArray[i] + *rhs.setArray[j]);
Note that I eliminated all of the extra parentheses because * has lower precedence than [], so the parentheses around setArray[i] and setArray[i] were redundant. I think the code is more readable this way.
Well really, if I can guess what's going on here, setArray is the internal storage of the Set class, so it's type will need to be redefined from Multinumber** to Multinumber*, in which case the call really should be
result.addElement(setArray[i] + rhs.setArray[j]);
EDIT Ugggh. None of the above will actually allow you to keep your polymorphism. You need to call new Rational somewhere, and the only reasonable place that I can think of is:
result.addElement( new Rational(*setArray[i] + *rhs.setArray[j]) );
This will work without having to redefine Set::addElement.
A better solution would be to redesign the whole thing so that it doesn't depend on polymorphism for numeric classes (because numeric classes really shouldn't be wrapped in pointers in most normal use).

(Obj) C++: Instantiate (reference to) class from template, access its members?

I'm trying to fix something in some Objective C++ (?!) code. I don't know either of those languages, or any of the relevant APIs or the codebase, so I'm getting stymied left and right.
Say I have:
Vector<char, sizeof 'a'>& sourceData();
sourceData->append('f');
When i try to compile that, I get:
error: request for member 'append' in 'WebCore::sourceData', which is of non-class type 'WTF::Vector<char, 1ul >& ()();
In this case, Vector is WTF::Vector (from WebKit or KDE or something), not STD::Vector. append() very much is supposed to be a member of class generated from this template, as seen in this documentation. It's a Vector. It takes the type the template is templated on.
Now, because I never write programs in Real Man's programming languages, I'm hella confused about the notations for references and pointers and dereferences and where we need them.
I ultimately want a Vector reference, because I want to pass it to another function with the signature:
void foobar(const Vector<char>& in, Vector<char>& out)
I'm guessing the const in the foobar() sig is something I can ignore, meaning 'dont worry, this won't be mangled if you pass it in here'.
I've also tried using .append rather than -> because isn't one of the things of C++ references that you can treat them more like they aren't pointers? Either way, its the same error.
I can't quite follow the error message: it makes it sound like sourceData is of type WTF:Vector<char, 1ul>&, which is what I want. It also looks from the those docs of WTF::Vector that when you make a Vector of something, you get an .append(). But I'm not familiar with templates, either, so I can't really tell i I'm reading that right.
EDIT:
(This is a long followup to Pavel Minaev)
WOW THANKS PROBLEM SOLVED!
I was actually just writing an edit to this post that I semi-figured out your first point after coming across a reference on the web that that line tells the compiler your forward declaring a func called sourceData() that takes no params and returns a Vector of chars. so a "non-class type" in this case means a type that is not an instance of a class. I interpreted that as meaning that the type was not a 'klass', i.e. the type of thing you would expect you could call like .addMethod(functionPointer).
Thanks though! Doing what you suggest makes this work I think. Somehow, I'd gotten it into my head (idk from where) that because the func sig was vector&, I needed to declare those as &'s. Like a stack vs. heap pass issue.
Anyway, that was my REAL problem, because I tried what you'd suggested about but that doesn't initialize the reference. You need to explicitly call the constructor, but then when I put anything in the constructor's args to disambiguate from being a forward decl, it failed with some other error about 'temporary's.
So in a sense, I still don't understand what is going on here fully, but I thank you heartily for fixing my problem. if anyone wants to supply some additional elucidation for the benefit of me and future google people, that would be great.
This:
Vector<char, sizeof 'a'>& sourceData();
has declared a global function which takes no arguments and returns a reference to Vector. The name sourceData is therefore of function type. When you try to access a member of that, it rightfully complains that it's not a class/struct/union, and operator-> is simply inapplicable.
To create an object instead, you should omit the parentheses (they are only required when you have any arguments to pass to the constructor, and must be omitted if there are none):
Vector<char, sizeof 'a'> sourceData;
Then you can call append:
sourceData.append('f');
Note that dot is used rather than -> because you have an object, not a pointer to object.
You do not need to do anything special to pass sourceData to a function that wants a Vector&. Just pass the variable - it will be passed by reference automatically:
foobar(sourceData, targetData);
Dipping your toes in C++ is never much fun. In this case, you've run into a couple of classic mistakes. First, you want to create an instance of Vector on the stack. In this case the empty () is interpreted instead as a declaratiton of a function called sourceData that takes no agruments and returns a reference to a Vector. The compiler is complaining that the resulting function is not a class (it's not). To create an instance of Vector instead, declare the instance without the () and remove the &. The parentheses are only required if you are passing arguments to the instance constructor and must be omitted if there are no arguments.
You want
Vector<char, sizeof 'a'> sourceData;
sourceData.append('f');
Vector<char, sizeof 'a'> outData; //if outData is not instantiated already
foobar(sourceData, outData);
This Wikipedia article gives a decent introduction to C++ references.

What am I doing wrong with this pointer cast?

I'm building a GUI class for C++ and dealing a lot with pointers. An example call:
mainGui.activeWindow->activeWidget->init();
My problem here is that I want to cast the activeWidget pointer to another type. activeWidget is of type GUI_BASE. Derived from BASE I have other classes, such as GUI_BUTTON and GUI_TEXTBOX. I want to cast the activeWidget pointer from GUI_BASE to GUI_TEXTBOX. I assume it would look something like this:
(GUI_TEXTBOX*)(mainGui.activeWindow->activeWidget)->function();
This isn't working, because the compiler still thinks the pointer is of type GUI_BASE. The following bit of code does work, however:
GUI_TEXTBOX *textbox_pointer;
textbox_pointer = (GUI_TEXTBOX*)mainGui.activeWindow->activeWidget;
textbox_pointer->function();
I'm hoping my problem here is just a syntax issue. Thanks for the help :)
The problem is that casts have lower precedence than the . -> () [] operators. You'll have to use a C++ style cast or add extra parentheses:
((GUI_TEXTBOX*)mainGui.activeWindow->activeWidget)->function(); // Extra parentheses
dynamic_cast<GUI_TEXTBOX*>(mainGui.activeWindow->activeWidget)->function(); // C++ style cast
You should not be using the C style cast.
You need to use the C++ dynamic cast. This will then allow you to test that the object is actually a GUI_TEXTBOX before you call the method on it.
GUI_TEXTBOX* textboxPointer = dynamic_cast<GUI_TEXTBOX*>(mainGui.activeWindow->activeWidget);
if (textboxPointer)
{
// If activeWidget is not a text box then dynamic_cast
// will return a NULL.
textboxPointer->textBoxMethod();
}
// or
dynamic_cast<GUI_TEXTBOX&>(*mainGui.activeWindow->activeWidget).textBoxMethod();
// This will throw bad_cast if the activeWidget is not a GUI_TEXTBOX
Note the C style cast and reinterpret_cast<>() are not guaranteed to work in this situation (Though on most compilers they will [but this is just an aspect of the implementation and you are getting lucky]). All bets are off if the object assigned to activeWidget actually uses multiple inheritance, in this situation you will start to see strange errors with most compilers if you do not use dynamic_cast<>().
You just need more parentheses:
((GUI_TEXTBOX*)(mainGui.activeWindow->activeWidget))->function();
Actually, this would work too:
((GUI_TEXTBOX*)mainGui.activeWindow->activeWidget)->function();
As others noted:
((GUI_TEXTBOX*)(mainGui.activeWindow->activeWidget))->function();
The reason is that the -> operator has a higher precedence than the type casting.
I'll put another plug in here for Steve Oualline's rule from "Practical C":
There are fifteen precedence rules in
C (&& comes before || comes before
?:). The practical programmer reduces
these to two:
1) Multiplication and division come
before addition and subtraction.
2) Put parentheses around everything
else.
And a final note: downcasts can be dangerous, see Martin York's answer for information on using dynamic_cast<> to perform the cast safely.
It's a matter of order of operators (operator precedence). Consider the code you were trying that didn't work:
(GUI_TEXTBOX*)(mainGui.activeWindow->activeWidget)->function();
Here, the -> operator takes higher precedence than your cast. That's why your other code sample works. In the other sample, you explicitly cast first, then call the function. To make it more streamlined try adding another set of parenthesis so that the code looks like:
((GUI_TEXTBOX*)(mainGui.activeWindow->activeWidget))->function();
There are two strategies. One is "fail fast": If you cast to the wrong type, then you will have an exception thrown, so you will notice immediately that you cast to the wrong type. Another one is "run fast": No checking of the destination type of the cast is done. This cast should only be used if you know that you can't be wrong or if you don't have a polymorphic type with the base or the derived. I recommend the following depending on your needs (remember to keep const when you cast):
dynamic_cast<GUI_TEXTBOX&>(*mainGui.activeWindow->activeWidget).function();
Fail fast: throws std::bad_cast if you cast to the wrong type.
static_cast<GUI_TEXTBOX*>(mainGui.activeWindow->activeWidget)->function();
Run fast: Doesn't do a runtime check. So it won't fail fast. Rather, it will produce undefined behavior if you cast to the wrong type. Beware!
((GUI_TEXTBOX*)(mainGui.activeWindow->activeWidget))->function();
-> has a higher precedence than (cast), so the member access is being done before the cast. See here for operator precedence: http://www.cppreference.com/wiki/operator_precedence
As stated above, you need more parentheses.
if( GUI_TEXTBOX* ptr =
dynamic_cast<GUI_TEXTBOX *>(mainGui.activeWindow->activeWidget) )
{
ptr->function();
}
The reason you want to do that is because the pointer you are trying to cast may not actually point to a GUI_TEXTBOX object and you want to make sure it does before calling textbox methods on it. C++'s dynamic cast is what you need for this.