Another useful tip is to use %*
to mean "all". For example:
echo off
set arg1=%1
set arg2=%2
shift
shift
fake-command /u %arg1% /p %arg2% %*
When you run:
test-command admin password foo bar
the above batch file will run:
fake-command /u admin /p password admin password foo bar
I may have the syntax slightly wrong, but this is the general idea.
Setting a bit
Use the bitwise OR operator (|
) to set a bit.
number |= 1UL << n;
That will set the n
th bit of number
. n
should be zero, if you want to set the 1
st bit and so on upto n-1
, if you want to set the n
th bit.
Use 1ULL
if number
is wider than unsigned long
; promotion of 1UL << n
doesn't happen until after evaluating 1UL << n
where it's undefined behaviour to shift by more than the width of a long
. The same applies to all the rest of the examples.
Clearing a bit
Use the bitwise AND operator (&
) to clear a bit.
number &= ~(1UL << n);
That will clear the n
th bit of number
. You must invert the bit string with the bitwise NOT operator (~
), then AND it.
Toggling a bit
The XOR operator (^
) can be used to toggle a bit.
number ^= 1UL << n;
That will toggle the n
th bit of number
.
Checking a bit
You didn't ask for this, but I might as well add it.
To check a bit, shift the number n to the right, then bitwise AND it:
bit = (number >> n) & 1U;
That will put the value of the n
th bit of number
into the variable bit
.
Changing the nth bit to x
Setting the n
th bit to either 1
or 0
can be achieved with the following on a 2's complement C++ implementation:
number ^= (-x ^ number) & (1UL << n);
Bit n
will be set if x
is 1
, and cleared if x
is 0
. If x
has some other value, you get garbage. x = !!x
will booleanize it to 0 or 1.
To make this independent of 2's complement negation behaviour (where -1
has all bits set, unlike on a 1's complement or sign/magnitude C++ implementation), use unsigned negation.
number ^= (-(unsigned long)x ^ number) & (1UL << n);
or
unsigned long newbit = !!x; // Also booleanize to force 0 or 1
number ^= (-newbit ^ number) & (1UL << n);
It's generally a good idea to use unsigned types for portable bit manipulation.
or
number = (number & ~(1UL << n)) | (x << n);
(number & ~(1UL << n))
will clear the n
th bit and (x << n)
will set the n
th bit to x
.
It's also generally a good idea to not to copy/paste code in general and so many people use preprocessor macros (like the community wiki answer further down) or some sort of encapsulation.
Best Answer
Here are the possible ways to take a unique pointer as an argument, as well as their associated meaning.
(A) By Value
In order for the user to call this, they must do one of the following:
To take a unique pointer by value means that you are transferring ownership of the pointer to the function/object/etc in question. After
newBase
is constructed,nextBase
is guaranteed to be empty. You don't own the object, and you don't even have a pointer to it anymore. It's gone.This is ensured because we take the parameter by value.
std::move
doesn't actually move anything; it's just a fancy cast.std::move(nextBase)
returns aBase&&
that is an r-value reference tonextBase
. That's all it does.Because
Base::Base(std::unique_ptr<Base> n)
takes its argument by value rather than by r-value reference, C++ will automatically construct a temporary for us. It creates astd::unique_ptr<Base>
from theBase&&
that we gave the function viastd::move(nextBase)
. It is the construction of this temporary that actually moves the value fromnextBase
into the function argumentn
.(B) By non-const l-value reference
This has to be called on an actual l-value (a named variable). It cannot be called with a temporary like this:
The meaning of this is the same as the meaning of any other use of non-const references: the function may or may not claim ownership of the pointer. Given this code:
There is no guarantee that
nextBase
is empty. It may be empty; it may not. It really depends on whatBase::Base(std::unique_ptr<Base> &n)
wants to do. Because of that, it's not very evident just from the function signature what's going to happen; you have to read the implementation (or associated documentation).Because of that, I wouldn't suggest this as an interface.
(C) By const l-value reference
I don't show an implementation, because you cannot move from a
const&
. By passing aconst&
, you are saying that the function can access theBase
via the pointer, but it cannot store it anywhere. It cannot claim ownership of it.This can be useful. Not necessarily for your specific case, but it's always good to be able to hand someone a pointer and know that they cannot (without breaking rules of C++, like no casting away
const
) claim ownership of it. They can't store it. They can pass it to others, but those others have to abide by the same rules.(D) By r-value reference
This is more or less identical to the "by non-const l-value reference" case. The differences are two things.
You can pass a temporary:
You must use
std::move
when passing non-temporary arguments.The latter is really the problem. If you see this line:
You have a reasonable expectation that, after this line completes,
nextBase
should be empty. It should have been moved from. After all, you have thatstd::move
sitting there, telling you that movement has occurred.The problem is that it hasn't. It is not guaranteed to have been moved from. It may have been moved from, but you will only know by looking at the source code. You cannot tell just from the function signature.
Recommendations
unique_ptr
, take it by value.unique_ptr
for the duration of that function's execution, take it byconst&
. Alternatively, pass a&
orconst&
to the actual type pointed to, rather than using aunique_ptr
.&&
. But I strongly advise against doing this whenever possible.How to manipulate unique_ptr
You cannot copy a
unique_ptr
. You can only move it. The proper way to do this is with thestd::move
standard library function.If you take a
unique_ptr
by value, you can move from it freely. But movement doesn't actually happen because ofstd::move
. Take the following statement:This is really two statements:
(note: The above code does not technically compile, since non-temporary r-value references are not actually r-values. It is here for demo purposes only).
The
temporary
is just an r-value reference tooldPtr
. It is in the constructor ofnewPtr
where the movement happens.unique_ptr
's move constructor (a constructor that takes a&&
to itself) is what does the actual movement.If you have a
unique_ptr
value and you want to store it somewhere, you must usestd::move
to do the storage.