Thread: Declaring constant references

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

    Declaring constant references

    This is a continuation of the problem here.
    I just defined my own ctype
    Code:
    class AnsiCType : public std::ctype<char>
    {
     public:
      AnsiCType(std::size_t refs = 0);
     private:
      mask ansi_table[table_size];
    };
    Now, I've run into a problem that I have an idea of how to solve, I just don't want to solve it that way.

    I'm trying to declare a ctype so that it can be defined based on the command line argument, but if there is no locale argument from the command line, it will default to AnsiCType. This is the outline that I have, and, obviously, it won't work.
    Code:
    const std::ctype<char>& ct; //obviously there will be an error here because it's not initialized
    if(there are command line arguments declaring a locale)
    
    std::locale loc(command line locale); ct = std::use_facet<std::ctype<char> >(loc); //another no no
    else {
    AnsiCType act; ct = act; //another big no no, so how do I get around this?
    }
    I need to have my ctype variable to be accessible within the scope of "main" because I'm passing it on as an argument to another function.

    The obvious solution is
    Code:
    if(there are command line arguments declaring a locale)
    
    std::locale loc(command line locale); const std::ctype<char>& ct = std::use_facet<std::ctype<char> >(loc); call_my_function(ct);
    else {
    AnsiCType act; call_my_function(act)
    There are several reasons I don't want to do this, the most important being that I don't want to have to handle command line arguments twice (once before, for reading in data files).

    Any help would be appreciated.

  2. #2
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    The problem is that if loc and/or act are automatic variables, they will go out of scope outside the if/else block. So you have to call the function in the same scope (or a nested scope) as that variable. That either means the function is called from two different places, or both variables are defined outside the if/else whether they are used or not. (Another option is to use dynamic allocation.)

    You could create another function and put most of main in it. Then call that function from the if or the else. That would make the most sense to me (the function would have a const std::ctype<char>& parameter).

  3. #3
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Just use a const pointer instead of a const reference. Then create a const reference out of it.

    EDIT: As in:

    Code:
    const foo *x = 0;
    
    if(something)
    {
        x = &blah;
    }
    else
    {
        x = &flarb;
    }
    
    const foo &xref = *x;
    Last edited by brewbuck; 11-02-2007 at 05:42 PM.

  4. #4
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    But you'd still have to move the variable declaration up a scope or use dynamic allocation.

  5. #5
    Registered User
    Join Date
    Oct 2005
    Posts
    271
    Thanks, brewbuck. It now compiles. However, now I have a problem with the behavior of my AnsiCType.

    First, here's how I rewrote my code
    Code:
      const std::ctype<char>* ct;
      if(command line argument for locale)
        {
          std::locale loc(command line argument for locale);
          ct = &std::use_facet<std::ctype<char> >(loc);
        }
      else
        {
          std::locale loc;
          const AnsiCType& act = std::use_facet<AnsiCType>(loc);
          ct = &act;
        }
      const std::ctype<char>& ctr = *ct;
      setStr2Id(a map container, a filestream, ctr);
    However, even if I use this redefined ctype, it does not properly sort upper ascii letters as "alpha".
    Here's my definition of setStr2Id
    Code:
    template<typename charT>
    void setStr2Id
    (Str2IdMap& s2i, std::ifstream& ifstr, const std::ctype<charT>& ct){
    
      std::string line;
      while(ifstr >> line)
        {
          const char* const c = line.c_str();
          std::string::size_type st = line.size();
          if(ct.scan_not(std::ctype_base::alpha, c, c + st) == c + st)
    	s2i.getId(line);
        }
    }
    Now, when I looked into "ct.scan_not" in my debugger, I got into this:
    Code:
      const char*
      ctype<char>::
      scan_not(mask __m, const char* __low, const char* __high) const
      {
        while (__low < __high 
    	   && (_M_table[static_cast<unsigned char>(*__low)] & __m) != 0)
          ++__low;
        return __low;
      }
    And while I could not see how _M_table was defined, I am pretty certain that it's not the masking table as I redefined it. So I thought I should try overriding the "scan_not" function in my AnsiCType class. Even then, my program went straight for the "scan_not" in the standard, and not my overridden one.

    So how do I get the compiler to use my "scan_not" function or my masking table rather then the predefined one?

    By the way, here's my AnsiCType constructor
    Code:
    AnsiCType::AnsiCType(std::size_t refs)
      : std::ctype<char>(ansi_table, false, refs)
    {
      std::copy(classic_table(),
    	    classic_table() + table_size,
    	    ansi_table);
      for(int i = 192; i < 223; i++)
        {
          if(i != 214)
    	ansi_table[i] = (mask) (alpha | upper | print | punct);
        }
      for(int i = 223; i < 256; i++)
        {
          if(i != 247)
    	ansi_table[i] = (mask) (alpha | lower | print | punct);
        }
    }

  6. #6
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Does the return value of use_facet require that the locale passed to it remain valid for the lifetime of the return value?

  7. #7
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Yes, because the locale is a container for facets, use_facet returns a reference to one of the facets in the locale, and the locale will destroy all facets when it dies. (If it is the last of its kind, at least. Locales are shallowly copied.)
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  8. #8
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    So that solution won't work because loc is local to the if (or else) block and will go out of scope before you finish using ct or ctr.

    That means that you still have to move the declaration of loc up a scope or use dynamic allocation.

    I would still add one more layer of a function that would effectively move the declaration up a scope but would still make things cleaner.

  9. #9
    Registered User
    Join Date
    Oct 2005
    Posts
    271
    Yup, daved, you were right. It kept throwing a segfault because locale was out of scope even though the ctype wasn't.

    And as for fixing my AnsiCType facet, turns out I had to do this
    Code:
          loc = std::locale(std::locale::classic(),
    			new AnsiCType);
          ct = &std::use_facet<std::ctype<char> >(loc);
    I read somewhere in a tutorial that I was supposed to do that, but my program wouldn't compile (which is why I was flailing about for a different solution), then hours of headaches later, I discovered that I forgot to include my header for the AnsiCType in my make target!!! I regret that this forum has a language filter. There are a few choice words that I would like to apply to myself, nincompoop being the least offensive.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Declaring and initialising constant nested arrays
    By officedog in forum C Programming
    Replies: 6
    Last Post: 10-28-2008, 09:55 AM
  2. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  3. We Got _DEBUG Errors
    By Tonto in forum Windows Programming
    Replies: 5
    Last Post: 12-22-2006, 05:45 PM
  4. load gif into program
    By willc0de4food in forum Windows Programming
    Replies: 14
    Last Post: 01-11-2006, 10:43 AM
  5. Warnings, warnings, warnings?
    By spentdome in forum C Programming
    Replies: 25
    Last Post: 05-27-2002, 06:49 PM