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. C++ Function objects - how to use them?

C++ Function objects - how to use them?

Scheduled Pinned Locked Moved C / C++ / MFC
c++questiongraphicshelptutorial
6 Posts 6 Posters 0 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.
  • I Offline
    I Offline
    Ilushka
    wrote on last edited by
    #1

    Hi All! Here goes the question: Mr. C++ has cleary descibed how to use function objects in Parhagraph 18.4 of his Book. The Sample code works OK, and if i use them with STL, everything`s OK Here is a simple sample: void Add7(int& out_Int) { out_Int += 7; } class AddNumber { public: int m_iToAdd; AddNumber(int in_iToAdd = 0) { m_iToAdd = in_iToAdd; } void operator()(int& out_Int) { out_Int += m_iToAdd; } }; class A { public: std::vector < int > m_vData; }; void main() { A tmp_a; tmp_a.m_vData.push_back(7); tmp_a.m_vData.push_back(5); tmp_a.m_vData.push_back(6); std::for_each(tmp_a.m_vData.begin(),tmp_a.m_vData.end(),Add7); std::for_each(tmp_a.m_vData.begin(),tmp_a.m_vData.end(),AddNumber(13)); } --- But when i try to use them some other way than in combination with STL, I get that: typedef void (*TraveseFuncPtr) (int&); void Add7(int& out_Int) { out_Int += 7; } class AddNumber { public: int m_iToAdd; AddNumber(int in_iToAdd = 0) { m_iToAdd = in_iToAdd; } void operator()(int& out_Int) { out_Int += m_iToAdd; } }; class A { public: std::vector < int > m_vData; void TraverseVector(TraveseFuncPtr in_func) { for (int i = 0; i < m_vData.size(); i++) { (*in_func)(m_vData[i]); } } }; void main() { A tmp_a; tmp_a.m_vData.push_back(7); tmp_a.m_vData.push_back(5); tmp_a.m_vData.push_back(6); tmp_a.TraverseVector(Add7); // All ok. tmp_a.TraverseVector(AddNumber(13)); //C2664 } --- And thats it. error C2664: 'TraverseVector' : cannot convert parameter 1 from 'class AddNumber' to 'void (__cdecl *)(int &)' No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called I tried to dig up STL source but hell the same for_each takes a CLASS (!) as a template parameter. No functions there. Who can say anything to this? Sincerely yours, Ilya Kalujny.

    A J A J K 5 Replies Last reply
    0
    • I Ilushka

      Hi All! Here goes the question: Mr. C++ has cleary descibed how to use function objects in Parhagraph 18.4 of his Book. The Sample code works OK, and if i use them with STL, everything`s OK Here is a simple sample: void Add7(int& out_Int) { out_Int += 7; } class AddNumber { public: int m_iToAdd; AddNumber(int in_iToAdd = 0) { m_iToAdd = in_iToAdd; } void operator()(int& out_Int) { out_Int += m_iToAdd; } }; class A { public: std::vector < int > m_vData; }; void main() { A tmp_a; tmp_a.m_vData.push_back(7); tmp_a.m_vData.push_back(5); tmp_a.m_vData.push_back(6); std::for_each(tmp_a.m_vData.begin(),tmp_a.m_vData.end(),Add7); std::for_each(tmp_a.m_vData.begin(),tmp_a.m_vData.end(),AddNumber(13)); } --- But when i try to use them some other way than in combination with STL, I get that: typedef void (*TraveseFuncPtr) (int&); void Add7(int& out_Int) { out_Int += 7; } class AddNumber { public: int m_iToAdd; AddNumber(int in_iToAdd = 0) { m_iToAdd = in_iToAdd; } void operator()(int& out_Int) { out_Int += m_iToAdd; } }; class A { public: std::vector < int > m_vData; void TraverseVector(TraveseFuncPtr in_func) { for (int i = 0; i < m_vData.size(); i++) { (*in_func)(m_vData[i]); } } }; void main() { A tmp_a; tmp_a.m_vData.push_back(7); tmp_a.m_vData.push_back(5); tmp_a.m_vData.push_back(6); tmp_a.TraverseVector(Add7); // All ok. tmp_a.TraverseVector(AddNumber(13)); //C2664 } --- And thats it. error C2664: 'TraverseVector' : cannot convert parameter 1 from 'class AddNumber' to 'void (__cdecl *)(int &)' No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called I tried to dig up STL source but hell the same for_each takes a CLASS (!) as a template parameter. No functions there. Who can say anything to this? Sincerely yours, Ilya Kalujny.

      A Offline
      A Offline
      Aaron Schaefer
      wrote on last edited by
      #2

      Yes, but what you have defined as the argument to the TraverseVector is simplay a function pointer: typedef void (*TraveseFuncPtr) (int&); Function pionters are not quite the same thing as function objects. If you want to define a function that accepts as a parameter a functor (some class which has an overloaded operator()), then you could make the function a template function and have the exact type of the class you wold pass in a template parameter. Maybe something like this: template void TraverseVector(_FunctorType in_func) { for (int i = 0; i < m_vData.size(); i++) { in_func(m_vData[i]); } } This should allow you to pass in an aribtrary type as an argument, so long as it had an overloaded operator() with the correct signature.

      1 Reply Last reply
      0
      • I Ilushka

        Hi All! Here goes the question: Mr. C++ has cleary descibed how to use function objects in Parhagraph 18.4 of his Book. The Sample code works OK, and if i use them with STL, everything`s OK Here is a simple sample: void Add7(int& out_Int) { out_Int += 7; } class AddNumber { public: int m_iToAdd; AddNumber(int in_iToAdd = 0) { m_iToAdd = in_iToAdd; } void operator()(int& out_Int) { out_Int += m_iToAdd; } }; class A { public: std::vector < int > m_vData; }; void main() { A tmp_a; tmp_a.m_vData.push_back(7); tmp_a.m_vData.push_back(5); tmp_a.m_vData.push_back(6); std::for_each(tmp_a.m_vData.begin(),tmp_a.m_vData.end(),Add7); std::for_each(tmp_a.m_vData.begin(),tmp_a.m_vData.end(),AddNumber(13)); } --- But when i try to use them some other way than in combination with STL, I get that: typedef void (*TraveseFuncPtr) (int&); void Add7(int& out_Int) { out_Int += 7; } class AddNumber { public: int m_iToAdd; AddNumber(int in_iToAdd = 0) { m_iToAdd = in_iToAdd; } void operator()(int& out_Int) { out_Int += m_iToAdd; } }; class A { public: std::vector < int > m_vData; void TraverseVector(TraveseFuncPtr in_func) { for (int i = 0; i < m_vData.size(); i++) { (*in_func)(m_vData[i]); } } }; void main() { A tmp_a; tmp_a.m_vData.push_back(7); tmp_a.m_vData.push_back(5); tmp_a.m_vData.push_back(6); tmp_a.TraverseVector(Add7); // All ok. tmp_a.TraverseVector(AddNumber(13)); //C2664 } --- And thats it. error C2664: 'TraverseVector' : cannot convert parameter 1 from 'class AddNumber' to 'void (__cdecl *)(int &)' No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called I tried to dig up STL source but hell the same for_each takes a CLASS (!) as a template parameter. No functions there. Who can say anything to this? Sincerely yours, Ilya Kalujny.

        J Offline
        J Offline
        jhwurmbach
        wrote on last edited by
        #3

        One question: Isn't a function object (also named Functor) an object which behaves like a function?. That means this object has an overloaded operator() returning whatever the object does. This could be the explanation why the STL wants a CLASS - it calls its operator(). For your Add7-Object it would look about like

        class Add7()
        {
        int operator()(int& out_Int)const
        {
        return out_Int + 7;
        };
        }

        This can be further complicated by making the class Add7 a template.


        My opinions may have changed, but not the fact that I am right.

        1 Reply Last reply
        0
        • I Ilushka

          Hi All! Here goes the question: Mr. C++ has cleary descibed how to use function objects in Parhagraph 18.4 of his Book. The Sample code works OK, and if i use them with STL, everything`s OK Here is a simple sample: void Add7(int& out_Int) { out_Int += 7; } class AddNumber { public: int m_iToAdd; AddNumber(int in_iToAdd = 0) { m_iToAdd = in_iToAdd; } void operator()(int& out_Int) { out_Int += m_iToAdd; } }; class A { public: std::vector < int > m_vData; }; void main() { A tmp_a; tmp_a.m_vData.push_back(7); tmp_a.m_vData.push_back(5); tmp_a.m_vData.push_back(6); std::for_each(tmp_a.m_vData.begin(),tmp_a.m_vData.end(),Add7); std::for_each(tmp_a.m_vData.begin(),tmp_a.m_vData.end(),AddNumber(13)); } --- But when i try to use them some other way than in combination with STL, I get that: typedef void (*TraveseFuncPtr) (int&); void Add7(int& out_Int) { out_Int += 7; } class AddNumber { public: int m_iToAdd; AddNumber(int in_iToAdd = 0) { m_iToAdd = in_iToAdd; } void operator()(int& out_Int) { out_Int += m_iToAdd; } }; class A { public: std::vector < int > m_vData; void TraverseVector(TraveseFuncPtr in_func) { for (int i = 0; i < m_vData.size(); i++) { (*in_func)(m_vData[i]); } } }; void main() { A tmp_a; tmp_a.m_vData.push_back(7); tmp_a.m_vData.push_back(5); tmp_a.m_vData.push_back(6); tmp_a.TraverseVector(Add7); // All ok. tmp_a.TraverseVector(AddNumber(13)); //C2664 } --- And thats it. error C2664: 'TraverseVector' : cannot convert parameter 1 from 'class AddNumber' to 'void (__cdecl *)(int &)' No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called I tried to dig up STL source but hell the same for_each takes a CLASS (!) as a template parameter. No functions there. Who can say anything to this? Sincerely yours, Ilya Kalujny.

          A Offline
          A Offline
          Andrew Walker
          wrote on last edited by
          #4

          One way to do what you want would be to make the traverse vector method a template method. I recommend against doing this, using STL means using all (or as much as you can manage) of it - so you should attempt to reuse tools like for_each wherever you can. for_each works along the same lines as the attached code, but may be optomised by the library for some template specialisations. The problem, passing extra information to a functor (function object), that you're putting forward is quite common, binders are a good place to look if you're interested in more generic solutions to this problem. class A { public: std::vector < int > m_vData; template void TraverseVector(F in_func) { for (int i = 0; i < m_vData.size(); i++) { in_func(m_vData[i]); cout << m_vData[i] << endl; } } };

          1 Reply Last reply
          0
          • I Ilushka

            Hi All! Here goes the question: Mr. C++ has cleary descibed how to use function objects in Parhagraph 18.4 of his Book. The Sample code works OK, and if i use them with STL, everything`s OK Here is a simple sample: void Add7(int& out_Int) { out_Int += 7; } class AddNumber { public: int m_iToAdd; AddNumber(int in_iToAdd = 0) { m_iToAdd = in_iToAdd; } void operator()(int& out_Int) { out_Int += m_iToAdd; } }; class A { public: std::vector < int > m_vData; }; void main() { A tmp_a; tmp_a.m_vData.push_back(7); tmp_a.m_vData.push_back(5); tmp_a.m_vData.push_back(6); std::for_each(tmp_a.m_vData.begin(),tmp_a.m_vData.end(),Add7); std::for_each(tmp_a.m_vData.begin(),tmp_a.m_vData.end(),AddNumber(13)); } --- But when i try to use them some other way than in combination with STL, I get that: typedef void (*TraveseFuncPtr) (int&); void Add7(int& out_Int) { out_Int += 7; } class AddNumber { public: int m_iToAdd; AddNumber(int in_iToAdd = 0) { m_iToAdd = in_iToAdd; } void operator()(int& out_Int) { out_Int += m_iToAdd; } }; class A { public: std::vector < int > m_vData; void TraverseVector(TraveseFuncPtr in_func) { for (int i = 0; i < m_vData.size(); i++) { (*in_func)(m_vData[i]); } } }; void main() { A tmp_a; tmp_a.m_vData.push_back(7); tmp_a.m_vData.push_back(5); tmp_a.m_vData.push_back(6); tmp_a.TraverseVector(Add7); // All ok. tmp_a.TraverseVector(AddNumber(13)); //C2664 } --- And thats it. error C2664: 'TraverseVector' : cannot convert parameter 1 from 'class AddNumber' to 'void (__cdecl *)(int &)' No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called I tried to dig up STL source but hell the same for_each takes a CLASS (!) as a template parameter. No functions there. Who can say anything to this? Sincerely yours, Ilya Kalujny.

            J Offline
            J Offline
            John R Shaw
            wrote on last edited by
            #5

            You are not passing a pointer to a function: tmp_a.TraverseVector(AddNumber(13)); (passing the return value of AddNumber(13) to TraverseVector(), which is void/nothing/nada). This is passing a pointer to a function: tmp_a.TraverseVector(AddNumber); Trust in the code Luke. Yea right!

            1 Reply Last reply
            0
            • I Ilushka

              Hi All! Here goes the question: Mr. C++ has cleary descibed how to use function objects in Parhagraph 18.4 of his Book. The Sample code works OK, and if i use them with STL, everything`s OK Here is a simple sample: void Add7(int& out_Int) { out_Int += 7; } class AddNumber { public: int m_iToAdd; AddNumber(int in_iToAdd = 0) { m_iToAdd = in_iToAdd; } void operator()(int& out_Int) { out_Int += m_iToAdd; } }; class A { public: std::vector < int > m_vData; }; void main() { A tmp_a; tmp_a.m_vData.push_back(7); tmp_a.m_vData.push_back(5); tmp_a.m_vData.push_back(6); std::for_each(tmp_a.m_vData.begin(),tmp_a.m_vData.end(),Add7); std::for_each(tmp_a.m_vData.begin(),tmp_a.m_vData.end(),AddNumber(13)); } --- But when i try to use them some other way than in combination with STL, I get that: typedef void (*TraveseFuncPtr) (int&); void Add7(int& out_Int) { out_Int += 7; } class AddNumber { public: int m_iToAdd; AddNumber(int in_iToAdd = 0) { m_iToAdd = in_iToAdd; } void operator()(int& out_Int) { out_Int += m_iToAdd; } }; class A { public: std::vector < int > m_vData; void TraverseVector(TraveseFuncPtr in_func) { for (int i = 0; i < m_vData.size(); i++) { (*in_func)(m_vData[i]); } } }; void main() { A tmp_a; tmp_a.m_vData.push_back(7); tmp_a.m_vData.push_back(5); tmp_a.m_vData.push_back(6); tmp_a.TraverseVector(Add7); // All ok. tmp_a.TraverseVector(AddNumber(13)); //C2664 } --- And thats it. error C2664: 'TraverseVector' : cannot convert parameter 1 from 'class AddNumber' to 'void (__cdecl *)(int &)' No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called I tried to dig up STL source but hell the same for_each takes a CLASS (!) as a template parameter. No functions there. Who can say anything to this? Sincerely yours, Ilya Kalujny.

              K Offline
              K Offline
              kuhx1980
              wrote on last edited by
              #6

              the definition of std::for_each template Function for_each (InputIterator first, InputIterator last, Function f) so, you can do this: // ======================================================= class A { public: std::vector m_vData; template // add this void TraverseVector(Function in_func) // ****** { for (int i = 0; i < m_vData.size(); i++) { (*in_func)(m_vData[i]); } } }; // =======================================================

              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