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
    Location
    Waterloo, Texas
    Posts
    5,708
    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:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 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
    Location
    Waterloo, Texas
    Posts
    5,708
    ah, well, actually you're calling the function:
    de_tolower()
    ...should be:
    bind2nd(de_tolower<the_type>, ct_de)
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 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
    Location
    Waterloo, Texas
    Posts
    5,708
    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:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  7. #7
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    ...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:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 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 10: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, 07:54 PM
  2. Troubleshooting Input Function
    By SiliconHobo in forum C Programming
    Replies: 14
    Last Post: 12-05-2007, 07:18 AM
  3. temperature sensors
    By danko in forum C Programming
    Replies: 22
    Last Post: 07-10-2007, 08:26 PM
  4. We Got _DEBUG Errors
    By Tonto in forum Windows Programming
    Replies: 5
    Last Post: 12-22-2006, 05:45 PM
  5. Including lib in a lib
    By bibiteinfo in forum C++ Programming
    Replies: 0
    Last Post: 02-07-2006, 02:28 PM

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