How to efficiently count the number of specific pointers?

I have the following C ++ code:

Some_class * temp1 = findTemp1(...); // returns NULL or a valid pointer Some_class * temp2 = findTemp2(...); // returns NULL or a valid pointer Some_class * temp3 = findTemp3(...); // returns NULL or a valid pointer 

Now I would like to calculate how many of them returned a valid pointer (0, 1, 2 or 3).

The only way I can think of is to simply check them one by one:

 int count = 0; if (temp1) count++; if (temp2) count++; if (temp3) count++; 

For 3 pointers, this is not so bad, but it does not scale well. Is there a more efficient way assuming that I am not overriding the findTempN function (possibly to go into the counter)?


Thanks so much for your quick answers! No, I'm not going to change the code, I'm just wondering what other options I had. I also realized that I cannot ask for something “scalable” if I use different literals to define three pointers. Of course, I didn’t think about what you answered :)

+7
source share
7 answers

Well, since it's C ++, we can go crazy looking for proximity ... for example:

 int count = !!temp1 + !!temp2 + !!temp3; 

Update: I probably should explain to Ivan what is happening here.

Assuming temp is any type of pointer !temp forces the pointer to be forced to bool (we want to do this) and negates the result (this is a side effect that we don’t need), This leads to true if the pointer is null and false , if the pointer is not null, which is the opposite of what we would like. Therefore, we will add one more ! to the beginning to deny the result again.

This leaves us with the addition of three bool values, which force them to int and perform the addition, after which we get our final result.

It may be easier for you to understand the fully equivalent

 int count = (bool)temp1 + (bool)temp2 + (bool)temp3; 

which I did not use because input !! three characters shorter (bool) (note: you might think this is a good trick, but when writing code it's really a bad idea to make decisions based on how many characters you have to enter).

The moral of this story is that such a thing can be called smart or cruel, depending on who you ask, but in C ++ there has traditionally been a high tolerance for atrocities.

Note that if the pointers were in some type of collection to start with, you could write much more beautiful code using std::count_if , for example:

 bool isNotNull(void* ptr) { return ptr != 0; } std::vector<Some_class*> vec; vec.push_back(temp1); vec.push_back(temp2); vec.push_back(temp3); int count = std::count_if(vec.begin(), vec.end(), isNotNull); 

Look at the action .

Or, as MSalters suggested very reasonably in the comments, you can lose the isNotNull function by counting pointers that are 0 and subtract this from all the pointers - but for this you need to know somehow what the number is (easy if they are in vector ):

 int count = vec.size() - std::count(vec.begin(), vec.end(), 0); 

Look at the action .

+11
source
 #define N 3 typedef Some_class *PointerGenerator(...); PointerGenerator funcs[N]; func[0] = &findTemp1; func[1] = &findTemp2; func[2] = &findTemp3; Some_class *ptrs[N]; for(size_t i = 0; i < N; ++i) ptrs[i] = func[i](); for(size_t i = 0; i < N; ++i) { if(ptrs[i]) ++count; } 

C ++ option 0x:

 int count = std::count_if(ptrs, ptrs + N, [](const Some_class *i) -> bool { return i != NULL; } ); 
0
source

The code you have is good enough, don't confuse it.

Introducing subtlety is a common beginner mistake, do not do this.

However, NULL is a valid pointer value, and you can do it for example. count += !!temp1 + !!temp2 + !!temp3 (but that would be a novice cheat, not really doing this).

Cheers and hth.,

0
source

If all the pointers are of the same type, put the pointers in the table, or if you cannot do this, make a table of pointers to pointers. then use std::count or std::count_if . Something like:

 SomeClass** pointerTable[] = { &temp1, &temp2, &temp3, // ... }; struct IndirectIsNoNull { bool operator()( SomeClass** p ) const { return *p != NULL; } }; // ... int validPointerCount = std::count_if( begin( pointerTable ), end( pointerTable ), IndirectIsNoNull() ); 
0
source

Enter a static counter.

 template<typename T> struct ValidPointer { static unsigned int count; }; template<typename T> unsigned int ValidPointer<T>::count = 0; template<typename T> static void isValid (const T* const p) { if(p) ValidPointer<T*>::count++; } 

Using:

 isValid(temp1); isValid(temp2); ... 

At any given time, if you want to receive then,

 unsigned int count = ValidPointer<Some_class*>::count; 

This code can be improved according to your requirement.

0
source

Do you need pointers afterwards? temp offers something else. In this case, you can eliminate those:

 int count = 0; if (findTemp1()) count++; if (findTemp2()) count++; if (findTemp3()) count++; 
0
source

Hide counter in class:

 class Some_class {}; typedef Some_class* (*FindFunction_t)(); Some_class* findTemp1() {return NULL;} Some_class* findTemp2() {return new Some_class;} Some_class* findTemp3() {return new Some_class;} class Finder { public: Finder() : count_(0) {} Some_class* CallAndCount(FindFunction_t fn) {return Count(fn());} int GetCount() const {return count_;} private: Some_class* Count(Some_class* p) {if(p) count_++; return p;} int count_; }; int main() { Finder f; Some_class* temp1 = f.CallAndCount(findTemp1); Some_class* temp2 = f.CallAndCount(findTemp2); Some_class* temp3 = f.CallAndCount(findTemp3); std::wcout << f.GetCount() << L"\n"; } 

The names are not the best, and there are memory leaks, but you should get this idea. I think this fits your scalability goal, although you will need to add template functions if your search functions accept parameters

-one
source

All Articles