Function call failing with bind2nd

This is a discussion on Function call failing with bind2nd within the C++ Programming forums, part of the General Programming Boards category; Hi all, I have a templated function which, when used with bind2nd, receives an error message of "no matching function ...

  1. #1
    Registered User
    Join Date
    Oct 2005
    Posts
    271

    Function call failing with bind2nd

    Hi all,

    I have a templated function which, when used with bind2nd, receives an error message of "no matching function for call to de_tolower()".

    Here's the relevant code:
    Code:
    ...
    
    template <typename T>
    void de_tolower(char& ch, const ctype<T>& ct)
    {
      ch = ct.tolower(ch);
    }
    
    int main(int argc, char* argv[])
    {
      locale loc_de("de_DE.utf8");
      const ctype<char>& ct_de = use_facet<ctype<char> >(loc_de);
    
      string str_de, str_en;
    
    ......
    
                //Error occurs in next line.
    	    for_each(str_de.begin(), str_de.end(), bind2nd(de_tolower(), ct_de));
    	    f_de_out << str_de << endl;
    
    .....
    Why isn't the compiler properly calling de_tolower?

  2. #2
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Posts
    5,439
    the compiler can't automatically deduce what type to instantiate the template on, so you need to be explicit, ie: de_tolower<wchar_t>...
    Code:
    int main(void){srand(time(0));for(double l=rand(),l0=0,l00=0;;l0+=0.1){for(double l000=0;l000
    <1;l000+=.001,l+=((double)rand()/RAND_MAX)/0x64,l00+=((sin(l*0x8*atan(l0)*l000-(l0*0x8*atan
    (l)))*0.5)+0.5)){l00-=floor(l00);for(size_t l0000=0,l00000=(size_t)(0x50*(l00));l0000<l00000;++l0000
    )putchar(0x20);putchar(0x61+(int)((double)rand()/RAND_MAX*0x1a));putchar('\n');}}return 0;}

  3. #3
    Registered User
    Join Date
    Oct 2005
    Posts
    271
    No, that was actually my previous version, and it didn't work either. And I always thought the compiler could guess the type based on the template argument that was being passed to a function.
    Please, correct me if I'm wrong.

  4. #4
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Posts
    5,439
    ah, well, actually you're calling the function:
    de_tolower()
    ...should be:
    bind2nd(de_tolower<the_type>, ct_de)
    Code:
    int main(void){srand(time(0));for(double l=rand(),l0=0,l00=0;;l0+=0.1){for(double l000=0;l000
    <1;l000+=.001,l+=((double)rand()/RAND_MAX)/0x64,l00+=((sin(l*0x8*atan(l0)*l000-(l0*0x8*atan
    (l)))*0.5)+0.5)){l00-=floor(l00);for(size_t l0000=0,l00000=(size_t)(0x50*(l00));l0000<l00000;++l0000
    )putchar(0x20);putchar(0x61+(int)((double)rand()/RAND_MAX*0x1a));putchar('\n');}}return 0;}

  5. #5
    Registered User
    Join Date
    Oct 2005
    Posts
    271
    Um, that gives me this:

    Code:
    /usr/bin/g++ -Wall -DCULL final_align.cpp -o final_align
    /usr/lib/gcc/i486-linux-gnu/4.0.3/../../../../include/c++/4.0.3/bits/stl_function.h: In instantiation of ‚:
    final_align.cpp:77:   instantiated from here
    /usr/lib/gcc/i486-linux-gnu/4.0.3/../../../../include/c++/4.0.3/bits/stl_function.h:429: error: ‚ is not a class, struct, or union type
    /usr/lib/gcc/i486-linux-gnu/4.0.3/../../../../include/c++/4.0.3/bits/stl_function.h:432: error: ‚ is not a class, struct, or union type
    /usr/lib/gcc/i486-linux-gnu/4.0.3/../../../../include/c++/4.0.3/bits/stl_function.h:435: error: ‚ is not a class, struct, or union type
    /usr/lib/gcc/i486-linux-gnu/4.0.3/../../../../include/c++/4.0.3/bits/stl_function.h:439: error: ‚ is not a class, struct, or union type
    /usr/lib/gcc/i486-linux-gnu/4.0.3/../../../../include/c++/4.0.3/bits/stl_function.h:445: error: ‚ is not a class, struct, or union type
    /usr/lib/gcc/i486-linux-gnu/4.0.3/../../../../include/c++/4.0.3/bits/stl_function.h:431: error: field ‚ invalidly declared function type
    /usr/lib/gcc/i486-linux-gnu/4.0.3/../../../../include/c++/4.0.3/bits/stl_function.h: In function ‚:
    final_align.cpp:77:   instantiated from here
    /usr/lib/gcc/i486-linux-gnu/4.0.3/../../../../include/c++/4.0.3/bits/stl_function.h:454: error: ‚ is not a class, struct, or union type
    /usr/lib/gcc/i486-linux-gnu/4.0.3/../../../../include/c++/4.0.3/bits/stl_function.h:455: error: ‚ is not a class, struct, or union type
    /usr/lib/gcc/i486-linux-gnu/4.0.3/../../../../include/c++/4.0.3/bits/stl_algo.h: In function ‚:
    final_align.cpp:77:   instantiated from here
    /usr/lib/gcc/i486-linux-gnu/4.0.3/../../../../include/c++/4.0.3/bits/stl_algo.h:158: error: no match for call to ‚
    make: *** [cull] Error 1
    Which, unfortunately, I can't make heads or tails of.

  6. #6
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Posts
    5,439
    I haven't used bind2nd before, but it looks as if the 'function' actually needs to be an object:

    Code:
    class de_tolower
    {
        public:
        
        template <typename T>
        void operator()(char& ch, const ctype<T>& ct)
        {
          ch = ct.tolower(ch);
        }
    };
    that may work, but you may need to define some typedef's in the structure for the STL, as well...
    Code:
    int main(void){srand(time(0));for(double l=rand(),l0=0,l00=0;;l0+=0.1){for(double l000=0;l000
    <1;l000+=.001,l+=((double)rand()/RAND_MAX)/0x64,l00+=((sin(l*0x8*atan(l0)*l000-(l0*0x8*atan
    (l)))*0.5)+0.5)){l00-=floor(l00);for(size_t l0000=0,l00000=(size_t)(0x50*(l00));l0000<l00000;++l0000
    )putchar(0x20);putchar(0x61+(int)((double)rand()/RAND_MAX*0x1a));putchar('\n');}}return 0;}

  7. #7
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Posts
    5,439
    ...and keep this line as is:
    for_each(str_de.begin(), str_de.end(), bind2nd(de_tolower(), ct_de));
    ...since you'd be instantiating a de_tolower object...
    Code:
    int main(void){srand(time(0));for(double l=rand(),l0=0,l00=0;;l0+=0.1){for(double l000=0;l000
    <1;l000+=.001,l+=((double)rand()/RAND_MAX)/0x64,l00+=((sin(l*0x8*atan(l0)*l000-(l0*0x8*atan
    (l)))*0.5)+0.5)){l00-=floor(l00);for(size_t l0000=0,l00000=(size_t)(0x50*(l00));l0000<l00000;++l0000
    )putchar(0x20);putchar(0x61+(int)((double)rand()/RAND_MAX*0x1a));putchar('\n');}}return 0;}

  8. #8
    carry on JaWiB's Avatar
    Join Date
    Feb 2003
    Location
    Seattle, WA
    Posts
    1,972
    The issue seems to be that std::ctype has a protected destructor (though I don't quite understand why that gives compile errors).

    However, I don't understand why you are trying to define a de_tolower function that accepts a ctype argument in the first place. Maybe it's just a naming issue.

    Will this not work?
    Code:
    struct de_tolower
    {
      typedef char first_argument_type;
      typedef std::locale second_argument_type;
      typedef void result_type;
    
      void operator()(char& ch, const std::locale& loc) const
      {
        ch = std::tolower(ch,loc);
      }
    
    };
    Still, it seems unnecessary...I'm not sure if there's a way using standard libraries, but with boost this seems to work:
    Code:
      std::transform(str_de.begin(), str_de.end(),str_de.begin(), boost::bind(std::tolower<char>,_1,loc_de));
    And no need to define a new function/functor
    "Think not but that I know these things; or think
    I know them not: not therefore am I short
    Of knowing what I ought."
    -John Milton, Paradise Regained (1671)

    "Work hard and it might happen."
    -XSquared

  9. #9
    Registered User
    Join Date
    Oct 2005
    Posts
    271
    Well, I ended up with these convoluted (and nonfunctional) alternatives after the most obvious attempts didn't work.

    Here's attempt 1:
    Code:
    transform(str_de.begin(), str_de.end(),str_de.begin(), ct_de.tolower());
    which gave me this error message:
    Code:
    final_align.cpp: In function ‚:
    final_align.cpp:77: error: no matching function for call to ‚
    /usr/lib/gcc/i486-linux-gnu/4.0.3/../../../../include/c++/4.0.3/bits/locale_facets.h:829: note: candidates are: char std::ctype<char>::tolower(char) const
    /usr/lib/gcc/i486-linux-gnu/4.0.3/../../../../include/c++/4.0.3/bits/locale_facets.h:846: note:                 const char* std::ctype<char>::tolower(char*, const char*) const
    Then I tried:
    Code:
    transform(str_de.begin(), str_de.end(),str_de.begin(), bind2nd(tolower(), loc_de));
    which gave me
    Code:
    final_align.cpp: In function ‚:
    /usr/include/ctype.h:116: error: too few arguments to function ‚
    final_align.cpp:77: error: at this point in file
    final_align.cpp:19: warning: unused variable ‚
    Then I tried
    Code:
    transform(str_de.begin(), str_de.end(),str_de.begin(), use_facet<ctype<char> >(loc_de).tolower());
    which gave me
    Code:
    /usr/bin/g++ -Wall -DCULL final_align.cpp -o final_align
    final_align.cpp: In function ‚:
    /usr/include/ctype.h:116: error: too few arguments to function ‚
    final_align.cpp:77: error: at this point in file
    final_align.cpp:19: warning: unused variable ‚
    make: *** [cull] Error 1
    tsmoon@odyssey:~/BACKUPEXCLUDE/lex_ac/Data/final$ make -k cull
    /usr/bin/g++ -Wall -DCULL final_align.cpp -o final_align
    final_align.cpp: In function ‚:
    final_align.cpp:77: error: no matching function for call to ‚
    /usr/lib/gcc/i486-linux-gnu/4.0.3/../../../../include/c++/4.0.3/bits/locale_facets.h:829: note: candidates are: char std::ctype<char>::tolower(char) const
    /usr/lib/gcc/i486-linux-gnu/4.0.3/../../../../include/c++/4.0.3/bits/locale_facets.h:846: note:                 const char* std::ctype<char>::tolower(char*, const char*) const
    final_align.cpp:77: error: expected `;' before ‚ token
    final_align.cpp:19: warning: unused variable ‚
    make: *** [cull] Error 1
    So my solutions got more and more complicated to the version you are looking at now.
    Anyway, I'll try your class based approach.

  10. #10
    Registered User
    Join Date
    Oct 2005
    Posts
    271
    Thanks, guys.

    The class based approach worked, and now I know that you have to pass a class object to bind2nd.

    If someone wouldn't mind answering though, why didn't the easiest approach below work in the first place?
    Code:
    transform(str_de.begin(), str_de.end(),str_de.begin(), ct_de.tolower());
    [EDIT]
    Ditch that. Josuttis says that to use user-defined function objects for function adapters, one must, "type members for the type of their arguments and the result," which I guess means that they have to be class wrapped.

    Anyway, thanks again, folks.
    Last edited by cunnus88; 04-14-2007 at 09:05 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. In over my head
    By Shelnutt2 in forum C Programming
    Replies: 1
    Last Post: 07-08-2008, 06:54 PM
  2. Troubleshooting Input Function
    By SiliconHobo in forum C Programming
    Replies: 14
    Last Post: 12-05-2007, 06:18 AM
  3. temperature sensors
    By danko in forum C Programming
    Replies: 22
    Last Post: 07-10-2007, 07:26 PM
  4. We Got _DEBUG Errors
    By Tonto in forum Windows Programming
    Replies: 5
    Last Post: 12-22-2006, 04:45 PM
  5. Including lib in a lib
    By bibiteinfo in forum C++ Programming
    Replies: 0
    Last Post: 02-07-2006, 01:28 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21