Reputation: 573
I have three LPCWSTR
string variables called A
, B
, C
.
I am assigning them from another function which can sometimes return nullptr
if something goes wrong. like this:
A = MyFunc();
B = MyFunc();
C = MyFunc();
Now, for some stuff with those variables, I need to check if only one of these variables is not nullptr
(only one of variables is assigned).
I tried to do this myself like:
if ((A == nullptr) && (B == nullptr) && (C <> nullptr)) {}
Any ideas about how to do this are welcome.
Upvotes: 12
Views: 3202
Reputation: 881113
Easy enough to do with:
int numSet = 0;
A = MyFunc(); if (A != nullptr) numSet++;
B = MyFunc(); if (B != nullptr) numSet++;
C = MyFunc(); if (C != nullptr) numSet++;
if (numSet == 1) // only one is set
You could also encapsulate the behaviour with a helper function:
LPCWSTR MyFuncWithCount(int &countSetProperly) {
LPCWSTR retVal = MyFunc();
if (retVal != nullptr) countSetProperly++;
return retVal;
}
int numSet = 0;
A = MyFuncWithCount(numSet);
B = MyFuncWithCount(numSet);
C = MyFuncWithCount(numSet);
if (numSet == 1) // only one is set
Next step up from there would be using a range-based for loop in conjunction with a braced init list, as per the following complete program:
#include <iostream>
#include <vector>
typedef void * LPCWSTR; // Couldn't be bothered including Windows stuff :-)
int main() {
// Only set two for test purposes.
LPCWSTR A = nullptr, B = nullptr, C = nullptr;
LPCWSTR D = &A, E = nullptr, F = &A;
int numSet = 0;
for (const auto &pointer: {A, B, C, D, E, F})
if (pointer != nullptr)
numSet++;
std::cout << "Count is " << numSet << std::endl;
}
Or you could embrace modern C++ in all its glory by using lambda functions, as per the following:
#include <iostream>
#include <vector>
typedef void * LPCWSTR; // Couldn't be bothered including Windows stuff :-)
int main() {
// Only set two for test purposes.
LPCWSTR A = nullptr, B = nullptr, C = nullptr;
LPCWSTR D = &A, E = nullptr, F = &A;
int numSet = 0;
[&numSet](const std::vector<LPCWSTR> &pointers) {
for (const auto &pointer: pointers)
if (pointer != nullptr)
numSet++;
} (std::vector<LPCWSTR>{A,B,C,D,E,F});
std::cout << "Count is " << numSet << std::endl;
}
That's probably overkill for your particular case however :-)
Upvotes: 15
Reputation: 372664
I'm not a huge fan of using techniques like the following in general, but you can use the fact that for any pointer ptr
that !!ptr
evaluates to 0 for a null pointer and 1 for a non-null pointer to write
if (!!A + !!B + !!C == 1) {
...
}
as a dense way to get this to work. It's essentially the same as @Davislor's solution but with a more compact "test if null" check.
This approach doesn't scale nearly as well as the accepted approach does, and it's trickier to read, but depending on your audience and who's reading the code it might do the trick nicely.
Upvotes: 3
Reputation: 15134
In C++, for backward-compatibility with C, the return value of a relational operator is an int
equal to 0
or 1
. So you can do:
if ( (a != nullptr) + (b != nullptr) + (c != nullptr) == 1 )
If you want to use logical operators only as logical operators, there are also disjunctive normal form and conjunctive normal form, albeit with more operations.
if ( (a && !b && !c) || (!a && b && !c) || (!a && !b && c) )
if ( (a || b || c) && (!a || !b) && (!a || !c) && (!b || !c) )
The former is not difficult to read in this simple case, compared to most of the other solutions, although it would quickly get too verbose if there were more possible solutions.
You can also stick them in any container, such as a std::array<LPCWSTR, 3>
, and do std::count( pointers.begin(), pointers.end(), nullptr)
(as Jarod42 suggested).
Upvotes: 4
Reputation: 217075
With std, you may do:
const auto vars = {A, B, C}; // Create initializer list.
const bool onlyOneNotNull =
(std::count(vars.begin(), vars.end(), nullptr) == (vars.size() - 1);
// then you may use find_if to retrieve the non null variable.
Upvotes: 11
Reputation: 31447
Here's one simple way:
int not_null = 0;
not_null += A != nullptr;
not_null += B != nullptr;
not_null += C != nullptr;
if (not_null == 1) {
/* Do stuff */
}
Check each for being nullptr
and increment a count if it is not. If the count comes out as 1
in the end, do your thing.
Upvotes: 7