Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Sending iterator items to other functions from in a for block....

Sending iterator items to other functions from in a for block....

Scheduled Pinned Locked Moved C / C++ / MFC
graphicsquestion
9 Posts 3 Posters 2 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    B Offline
    Ben Aldhouse
    wrote on last edited by
    #1

    Here is some code from the draw function in my custom control. I am using a vector to contain data concerning portions of the control. This code works. You will surely agree with me, though, that using the iterator 'x' to identify vector members in called functions is probably a tad on the clunky side. I have had a go at sending pointers to vector members. I gave up with this. I think this might not be the right way to go either. What it is the correct, elegant way to do this?

    vector::iterator slider;
    for ( slider=sliderVector.begin() ; slider != sliderVector.end(); slider++ )
    {
    	
    	theSliderRect.left = theDrawRect.left+(x-2)\*sliderWidth;
    	theSliderRect.right = theSliderRect.left + sliderWidth;
    
    	(\*slider).m\_TextBoxSize = m\_TextBoxSize;		
    	(\*slider).sliderRect = (RECT)theSliderRect;
    	
    	tempRect=theSliderRect;
    	tempRect.right=tempRect.right-4;
    
    	DrawBackground(&theMemDC,tempRect);
    
    	if (m\_currentSlider != x-1){
    		(\*slider).m\_bFlashFocus = FALSE; 
    	}
    	else{
    		(\*slider).m\_bFlashFocus = TRUE; 
    	}
    
    	DrawButtonsByID(&theMemDC, theSliderRect, x-1);
    	DrawThumbSliderByID(&theMemDC, theSliderRect, x-1);
    	DrawSliderLabelByID(&theMemDC, theSliderRect, x-1);
    	x++;
    }
    
    M 1 Reply Last reply
    0
    • B Ben Aldhouse

      Here is some code from the draw function in my custom control. I am using a vector to contain data concerning portions of the control. This code works. You will surely agree with me, though, that using the iterator 'x' to identify vector members in called functions is probably a tad on the clunky side. I have had a go at sending pointers to vector members. I gave up with this. I think this might not be the right way to go either. What it is the correct, elegant way to do this?

      vector::iterator slider;
      for ( slider=sliderVector.begin() ; slider != sliderVector.end(); slider++ )
      {
      	
      	theSliderRect.left = theDrawRect.left+(x-2)\*sliderWidth;
      	theSliderRect.right = theSliderRect.left + sliderWidth;
      
      	(\*slider).m\_TextBoxSize = m\_TextBoxSize;		
      	(\*slider).sliderRect = (RECT)theSliderRect;
      	
      	tempRect=theSliderRect;
      	tempRect.right=tempRect.right-4;
      
      	DrawBackground(&theMemDC,tempRect);
      
      	if (m\_currentSlider != x-1){
      		(\*slider).m\_bFlashFocus = FALSE; 
      	}
      	else{
      		(\*slider).m\_bFlashFocus = TRUE; 
      	}
      
      	DrawButtonsByID(&theMemDC, theSliderRect, x-1);
      	DrawThumbSliderByID(&theMemDC, theSliderRect, x-1);
      	DrawSliderLabelByID(&theMemDC, theSliderRect, x-1);
      	x++;
      }
      
      M Offline
      M Offline
      Maximilien
      wrote on last edited by
      #2

      Huh? What type is "X"? I assume it is an int (or long) since you add it to a CRect internal value. In what way does it identify a vector element? it is not clear.

      Nihil obstat

      B 1 Reply Last reply
      0
      • M Maximilien

        Huh? What type is "X"? I assume it is an int (or long) since you add it to a CRect internal value. In what way does it identify a vector element? it is not clear.

        Nihil obstat

        B Offline
        B Offline
        Ben Aldhouse
        wrote on last edited by
        #3

        Sorry, I should have clearer. The function calls I refer to are at the bottom of that block of code

        	DrawButtonsByID(&theMemDC, theSliderRect, x-1);
        	DrawThumbSliderByID(&theMemDC, theSliderRect, x-1);
        	DrawSliderLabelByID(&theMemDC, theSliderRect, x-1);
        

        The 'x' becomes 'id' in the called function below which dereferences the vector member that is the same as the iterator in that first for loop block I posted. I know this is murky. That's why I want to make nicer.

        void CScrollBarEx::DrawThumbSliderByID(CDC* inDC, CRect inDrawRect, short id)
        {
        // Override this to draw the thumb slider

        CRect		theThumbSliderRect;
        COLORREF	theThumbSliderColor = GetSysColor(COLOR\_3DFACE);
        COLORREF	theThumbSliderTextColor = GetSysColor(COLOR\_WINDOWTEXT);
        
        ASSERT(inDC != NULL);
        
        if (sliderVector\[id\].m\_bThumbSliderDownFlag && sliderVector\[m\_currentSlider\].m\_bTrackThumbSliderFlag)
        {	
        	//theThumbSliderColor = sliderVector\[m\_currentSlider\].m\_ThumbSliderTrackColor;
        	theThumbSliderColor = sliderVector\[id\].m\_ThumbSliderTrackColor;
        	theThumbSliderTextColor = m\_ThumbSliderTextColor;
        }
        

        ...

        S 1 Reply Last reply
        0
        • B Ben Aldhouse

          Sorry, I should have clearer. The function calls I refer to are at the bottom of that block of code

          	DrawButtonsByID(&theMemDC, theSliderRect, x-1);
          	DrawThumbSliderByID(&theMemDC, theSliderRect, x-1);
          	DrawSliderLabelByID(&theMemDC, theSliderRect, x-1);
          

          The 'x' becomes 'id' in the called function below which dereferences the vector member that is the same as the iterator in that first for loop block I posted. I know this is murky. That's why I want to make nicer.

          void CScrollBarEx::DrawThumbSliderByID(CDC* inDC, CRect inDrawRect, short id)
          {
          // Override this to draw the thumb slider

          CRect		theThumbSliderRect;
          COLORREF	theThumbSliderColor = GetSysColor(COLOR\_3DFACE);
          COLORREF	theThumbSliderTextColor = GetSysColor(COLOR\_WINDOWTEXT);
          
          ASSERT(inDC != NULL);
          
          if (sliderVector\[id\].m\_bThumbSliderDownFlag && sliderVector\[m\_currentSlider\].m\_bTrackThumbSliderFlag)
          {	
          	//theThumbSliderColor = sliderVector\[m\_currentSlider\].m\_ThumbSliderTrackColor;
          	theThumbSliderColor = sliderVector\[id\].m\_ThumbSliderTrackColor;
          	theThumbSliderTextColor = m\_ThumbSliderTextColor;
          }
          

          ...

          S Offline
          S Offline
          Stefan_Lang
          wrote on last edited by
          #4

          So you're accessing a vector with an index that comes from a variable of unknown type and origin. Not a lot of information to work with. Why do you think this is a problem? Is there a reason why you think x is not the appropriate index to use? Until you explain what x is and where you got it from, it's hard for us to understand your problem - if there is one. Since the code works, the only suggestion I can make at this point is to rename x to something more ... self-explanatory, and add a few comments to explain what's going on (while you're still able to understand it). That may be helpful if you need to fix it in a year or two. P.S.: There's one other suggestion I can think of: instead of passing x to those functions, pass a reference to the vector element. While technically that is the same as passing a vactor index, it removes the dependency between those functions and the entire vector.

          B 1 Reply Last reply
          0
          • S Stefan_Lang

            So you're accessing a vector with an index that comes from a variable of unknown type and origin. Not a lot of information to work with. Why do you think this is a problem? Is there a reason why you think x is not the appropriate index to use? Until you explain what x is and where you got it from, it's hard for us to understand your problem - if there is one. Since the code works, the only suggestion I can make at this point is to rename x to something more ... self-explanatory, and add a few comments to explain what's going on (while you're still able to understand it). That may be helpful if you need to fix it in a year or two. P.S.: There's one other suggestion I can think of: instead of passing x to those functions, pass a reference to the vector element. While technically that is the same as passing a vactor index, it removes the dependency between those functions and the entire vector.

            B Offline
            B Offline
            Ben Aldhouse
            wrote on last edited by
            #5

            I have spent some time trying to write code to send a reference to the vector element. I think I might have had trouble extracting this from the iterator. I must have somehow persuaded myself that there was some reason as to why passing a reference to a vector element from an iterator was a bad idea. I was just wondering if anyone knew if there is some sort of trap here - . I would probably be happier doing it this way if it is straightforward and safe. It seems more elegant. I don't really want to get bogged down in making the changes, though, if there is some inherent problem. The functions in the iterator block use and possibly change the data in the vector element but don't call any further functions that use the vector element. There is only a single thread accessing the vector.

            S 1 Reply Last reply
            0
            • B Ben Aldhouse

              I have spent some time trying to write code to send a reference to the vector element. I think I might have had trouble extracting this from the iterator. I must have somehow persuaded myself that there was some reason as to why passing a reference to a vector element from an iterator was a bad idea. I was just wondering if anyone knew if there is some sort of trap here - . I would probably be happier doing it this way if it is straightforward and safe. It seems more elegant. I don't really want to get bogged down in making the changes, though, if there is some inherent problem. The functions in the iterator block use and possibly change the data in the vector element but don't call any further functions that use the vector element. There is only a single thread accessing the vector.

              S Offline
              S Offline
              Stefan_Lang
              wrote on last edited by
              #6

              You didn't use an actual iterator anywhere in the code that you posted, so I don't see the problem. When a function argument is declared as a reference, you can just pass a vector element, such as sliderVector[id]. If you do have an iterator, then you can just dereference it to get the vector element and pass that instead. If you wish to pass a pointer instead, just use the 'address-of' operator:

              void bar_ref(double& element) {
              element *= 2.0;
              }
              void bar_ptr(double* p_element) {
              *p_element += 3.0;
              }
              void foo() {
              std::vector<double> myvec(2); // size = 2
              myvec[0] = 3.1415;
              myvec[1] = 2.718;
              for (std::size_t i = 0; i < myvec.size(); ++i) {
              bar_ref(myvec[i]); // passing element by reference
              bar_ptr(&(myvec[i])); // passing element by pointer
              }
              for (auto it = myvec.begin(); it != myvec.end(); ++it) {
              bar_ref(*it); // passing vector element by reference from iterator
              bar_ptr(&(*it)); // passing vector element by pointer from iterator
              }
              }

              The only possible trap I see is trying to pass an iterator directly when a pointer is expected. An iterator may behave like a pointer, but, while - depending on the implementation - it may actually auto-convert to a valid pointer (I know VS 2003 did that), you shouldn't rely on that. (e. g. VS2010 doesn't accept it)

              B 2 Replies Last reply
              0
              • S Stefan_Lang

                You didn't use an actual iterator anywhere in the code that you posted, so I don't see the problem. When a function argument is declared as a reference, you can just pass a vector element, such as sliderVector[id]. If you do have an iterator, then you can just dereference it to get the vector element and pass that instead. If you wish to pass a pointer instead, just use the 'address-of' operator:

                void bar_ref(double& element) {
                element *= 2.0;
                }
                void bar_ptr(double* p_element) {
                *p_element += 3.0;
                }
                void foo() {
                std::vector<double> myvec(2); // size = 2
                myvec[0] = 3.1415;
                myvec[1] = 2.718;
                for (std::size_t i = 0; i < myvec.size(); ++i) {
                bar_ref(myvec[i]); // passing element by reference
                bar_ptr(&(myvec[i])); // passing element by pointer
                }
                for (auto it = myvec.begin(); it != myvec.end(); ++it) {
                bar_ref(*it); // passing vector element by reference from iterator
                bar_ptr(&(*it)); // passing vector element by pointer from iterator
                }
                }

                The only possible trap I see is trying to pass an iterator directly when a pointer is expected. An iterator may behave like a pointer, but, while - depending on the implementation - it may actually auto-convert to a valid pointer (I know VS 2003 did that), you shouldn't rely on that. (e. g. VS2010 doesn't accept it)

                B Offline
                B Offline
                Ben Aldhouse
                wrote on last edited by
                #7

                Thanks for this! I will certainly give this a go and let you know how I get on. It might not be for a few weeks, though...

                1 Reply Last reply
                0
                • S Stefan_Lang

                  You didn't use an actual iterator anywhere in the code that you posted, so I don't see the problem. When a function argument is declared as a reference, you can just pass a vector element, such as sliderVector[id]. If you do have an iterator, then you can just dereference it to get the vector element and pass that instead. If you wish to pass a pointer instead, just use the 'address-of' operator:

                  void bar_ref(double& element) {
                  element *= 2.0;
                  }
                  void bar_ptr(double* p_element) {
                  *p_element += 3.0;
                  }
                  void foo() {
                  std::vector<double> myvec(2); // size = 2
                  myvec[0] = 3.1415;
                  myvec[1] = 2.718;
                  for (std::size_t i = 0; i < myvec.size(); ++i) {
                  bar_ref(myvec[i]); // passing element by reference
                  bar_ptr(&(myvec[i])); // passing element by pointer
                  }
                  for (auto it = myvec.begin(); it != myvec.end(); ++it) {
                  bar_ref(*it); // passing vector element by reference from iterator
                  bar_ptr(&(*it)); // passing vector element by pointer from iterator
                  }
                  }

                  The only possible trap I see is trying to pass an iterator directly when a pointer is expected. An iterator may behave like a pointer, but, while - depending on the implementation - it may actually auto-convert to a valid pointer (I know VS 2003 did that), you shouldn't rely on that. (e. g. VS2010 doesn't accept it)

                  B Offline
                  B Offline
                  Ben Aldhouse
                  wrote on last edited by
                  #8

                  Thanks very much for showing me how this can be done, Stefan. I have tried your method and it works perfectly. I have thought some more about what I'm trying to achieve, though, and have come to the conclusion that since the vector array has class scope and that its members don't themselves know, or need to know, whether they are the current item in the 'for' block (where I've got the iterator) - the more elegant solution would, I guess, involve just sending an (integer) identifier for the required element. Your help is very much appreciated. Your correspondence has helped my thought process a lot. Cheers, Ben

                  S 1 Reply Last reply
                  0
                  • B Ben Aldhouse

                    Thanks very much for showing me how this can be done, Stefan. I have tried your method and it works perfectly. I have thought some more about what I'm trying to achieve, though, and have come to the conclusion that since the vector array has class scope and that its members don't themselves know, or need to know, whether they are the current item in the 'for' block (where I've got the iterator) - the more elegant solution would, I guess, involve just sending an (integer) identifier for the required element. Your help is very much appreciated. Your correspondence has helped my thought process a lot. Cheers, Ben

                    S Offline
                    S Offline
                    Stefan_Lang
                    wrote on last edited by
                    #9

                    Glad I could be of help. As for your conclusion, keep in mind that sending an ID of the element requires you to also pass the container that this ID refers to! Otherwise the function won't know what to do with that ID. Whether that ID is an iterator or index value doesn't matter in this regard - neither have an inherent knowledge of the container they refer to. If the container is class scope, and you pass an ID to a class member function, that would work. But from a design view, doing so would still be questionable as the function actually shouldn't need to care about the rest of the container - you have introduced an unnecessary dependency. If at some point you realize you want to use that same function for elements not related to this class, you cannot easily do it, due to that dependency.

                    1 Reply Last reply
                    0
                    Reply
                    • Reply as topic
                    Log in to reply
                    • Oldest to Newest
                    • Newest to Oldest
                    • Most Votes


                    • Login

                    • Don't have an account? Register

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • World
                    • Users
                    • Groups