Author Topic: Const correctness trouble  (Read 12294 times)

Krice

  • (Banned)
  • Rogueliker
  • ***
  • Posts: 2316
  • Karma: +0/-2
    • View Profile
    • Email
Const correctness trouble
« on: February 25, 2011, 07:05:15 PM »
I'd like to know if there is a simple solution for this C++ problem. I think all of my output routines take non-const pointers for text, but std::string is such a handy tool. However it's const only. It would be difficult to rewrite output routines, since a lot of data is non-const. But what about creating const versions of output routines?

Ari Rahikkala

  • 7DRL Reviewer
  • Rogueliker
  • *
  • Posts: 64
  • Karma: +0/-0
    • View Profile
    • Email
Re: Const correctness trouble
« Reply #1 on: February 26, 2011, 03:59:09 AM »
C++ doesn't deal well with programs that aren't const-correct throughout. No, really. When even the FQA says you should just bite the bullet, you're best off not resisting. I'm not sure why a lot of data being non-const would pose a problem, are you familiar with the const correctness rules?

Z

  • Rogueliker
  • ***
  • Posts: 905
  • Karma: +0/-0
    • View Profile
    • Z's Roguelike Stuff
Re: Const correctness trouble
« Reply #2 on: February 26, 2011, 12:55:37 PM »
I don't know where your problem is. Usually you should just add const wherever the data does not change and you should be allright. Output routines do not change what they output, so adding const to them should be OK. Maybe you could post a relevant part?

Krice

  • (Banned)
  • Rogueliker
  • ***
  • Posts: 2316
  • Karma: +0/-2
    • View Profile
    • Email
Re: Const correctness trouble
« Reply #3 on: February 26, 2011, 05:24:02 PM »
I don't know where your problem is.

In huge amount of non-const text data.

Kalantir

  • Newcomer
  • Posts: 31
  • Karma: +0/-0
    • View Profile
Re: Const correctness trouble
« Reply #4 on: February 26, 2011, 05:33:00 PM »
What do you mean when you say string is const only?  Are you talking about string.c_str()?

We need more info to understand what your problem is, but here is the rundown on const correctness.

Code: [Select]
class foo
{
private:
    const int bar;
    int someValue;
public:
    foo(int foobar) : bar(foobar)
    {
        someValue = 0;
    }
    int GetValue() const
    {
        return someValue;
    }
    const int GetBar()
    {
        someValue++;
        return bar;
    }
};

Ok, clearly this class doesn't really do anything useful.  It's just for example.  bar is a const int, which means to initialize it we have to do something special with our constructor(: bar(foobar)) in order to initialize it.
GetValue returns an int, but is a const function because it does not modify any variables.  GetBar is not a const function because it modifies someValue, but it does return a const int(in this case, bar).

Technically, you could write any program without using const, but it's important to use it when applicable for readability and to protect against bugs resulting from variables(which should be const) being modified.
« Last Edit: February 26, 2011, 06:01:13 PM by Kalantir »

Krice

  • (Banned)
  • Rogueliker
  • ***
  • Posts: 2316
  • Karma: +0/-2
    • View Profile
    • Email
Re: Const correctness trouble
« Reply #5 on: February 26, 2011, 06:56:00 PM »
What do you mean when you say string is const only?  Are you talking about string.c_str()?

Yes, you can't take c_str and show it with routines that don't use const parameters, can you.

I think one of the biggest problem was item menus. They were constructed as text and yes, everything is non-const. I fixed that one by changing item menu so that it creates a pointer list to items. Then item names can be shown with item class routine, you don't even need to construct it as text. Of course I had a class that created a list of item ids with the text menu. Now some of the routines look like this:

Code: [Select]
void K_Itemlist::Clear()
{
item_list_ids.clear();
im_itemlist->Clear();
}

void K_Itemlist::Add(U_Item *i)
{
item_list_ids.push_back(i->Get_Object_Id());
im_itemlist->Add_Item(i);
}

There is a double list of everything... but it's simple enough, because the list is just constructed again when it changes. Edit: Well, now when I look at it I guess item_list_ids could be removed, since the item list contains items and the id can be get from there. Edit2: I think K_Itemlist class can be removed, since it's just a wrapper for  Item_Menu class.
« Last Edit: February 26, 2011, 07:01:54 PM by Krice »

Kalantir

  • Newcomer
  • Posts: 31
  • Karma: +0/-0
    • View Profile
Re: Const correctness trouble
« Reply #6 on: February 26, 2011, 08:02:58 PM »
Yes, you can't take c_str and show it with routines that don't use const parameters, can you.

Are they library functions or your own functions.  If they are your own functions you should be able to pass it by reference or pointer and deal with it from there.  If they are library functions which require (char *), you might be better off using c style strings or copying the string to a char * before passing it.

An alternative is to make your own string class which uses char * as it's underlying storage and have a function similar to c_str that returns a reference to it's own storage.  This could probably be seen as unsafe though, as private variables are only supposed to be modified by the classes member functions.  Honestly I don't even know 100% if this is possible, just an idea.

Another alternative still, if the function that takes char * is part of a library you are using, you could make a copy of the header file and change it to use std::string instead.  You could probably accomplish most of the work with a find and replace feature

Ok, I have one last idea.  You can probably modify std::string itself by adding a function which returns a char *.  It would probably be as simple as copy and paste c_str() with some slight modifications.  I imagine it probably typecasts it to const before returning it, as it's not const internally.  It's probably a matter of removing the typecast.

Just found this through google
Code: [Select]
void g (const char& c)
{
  val = f(const_cast<char&>(c));
}

It appeared to work for the person who posted the thread.  But someone warns not to use it unless you are absolutely sure it will not be altered on the other end or it could cause a fault.  This probably goes for the method of altering the string class as well
« Last Edit: February 26, 2011, 08:50:00 PM by Kalantir »

Krice

  • (Banned)
  • Rogueliker
  • ***
  • Posts: 2316
  • Karma: +0/-2
    • View Profile
    • Email
Re: Const correctness trouble
« Reply #7 on: February 27, 2011, 09:58:44 AM »
you could make a copy of the header file and change it to use std::string instead.

I don't really want to break the non-const gui system (text output, menus, windows, etc.) so maybe there is no clever solution for this. This far I have copied the string to non-const array. It's not that bad I guess, some minor loss of speed. Besides I don't use std::string that much, but in some places it's really good.
« Last Edit: February 27, 2011, 10:01:10 AM by Krice »

Kalantir

  • Newcomer
  • Posts: 31
  • Karma: +0/-0
    • View Profile
Re: Const correctness trouble
« Reply #8 on: February 27, 2011, 06:57:40 PM »
I don't really want to break the non-const gui system

I wasn't saying you should change it to use const so that you can pass it a c_str.  I was thinking you would change it from this
Code: [Select]
function(char *input)

to pass by pointer like this
Code: [Select]
function(std::string *input)

or pass by reference like this
Code: [Select]
function(std::string &input)

It would still be non-const.

A similar approach would be to simply overload the functions so you could pass const or non const, but it sounds like you don't want to do that.

But, if copying it over to an array works without causing any noticeable loss of speed, than it really is the easiest solution
« Last Edit: February 27, 2011, 07:46:49 PM by Kalantir »