By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,750 Members | 1,214 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,750 IT Pros & Developers. It's quick & easy.

Constness Complications

P: n/a

Here's two functions, a "const version" and a "non-const version":
char* GetFirstT(char* p)
{
for ( ; *p; ++p)
{
if ( *p == 't' ) return p;
}

return 0;
}

const char* GetFirstT(const char* p)
{
for ( ; *p; ++p)
{
if ( *p == 't' ) return p;
}

return 0;
}

signed main()
{
char the_alphabet[] = "abcdefghijklmnopqrstuvwxyz";

char* p_t = GetFirstT(the_alphabet);
}
See how I have to define two functions, is there any handy around that?
Would I have to do the following:

const char* GetFirstT(const char* p)
{
for ( ; *p; ++p)
{
if ( *p == 't' ) return p;
}

return 0;
}

char* GetFirstT(char* p)
{
return const_cast<char*>( GetFirstT(p) );
}
-JKop

Jul 22 '05 #1
Share this Question
Share on Google+
14 Replies


P: n/a
JKop <NU**@NULL.NULL> wrote in news:i9******************@news.indigo.ie:

Here's two functions, a "const version" and a "non-const version":
char* GetFirstT(char* p)
{
for ( ; *p; ++p)
{
if ( *p == 't' ) return p;
}

return 0;
}

const char* GetFirstT(const char* p)
{
for ( ; *p; ++p)
{
if ( *p == 't' ) return p;
}

return 0;
}

signed main()
{
char the_alphabet[] = "abcdefghijklmnopqrstuvwxyz";

char* p_t = GetFirstT(the_alphabet);
}
See how I have to define two functions, is there any handy around that?


No, you dont need to define both of them. See below.

#include <iostream>

char const* get_first_of(char const* s, char c)
{
for (; *s && *s != c; ++s);
return s;
}

int main()
{
char s[] = "abcdefghijklmnopqrstuvwxyz";
const char cs[] = "abcdefghijklmnopqrstuvwxyz";

const char* p1 = get_first_of(s, 'c');
const char* p2 = get_first_of(cs, 't');

std::cout << p1 << '\n'
<< p2 << '\n';

return 0;
}

When a function specifies its argument as const, it clearly means that it
won't modify that. Const-specifier can be implicitly hooked on.

Cheers.
--
:: bartekd / o2 pl
:: "out of confusion comes chaos -- out of chaos comes confusion and fear
:: -- then comes lunch."

Jul 22 '05 #2

P: n/a
JKop wrote:
See how I have to define two functions, is there any handy around that?
Would I have to do the following:

const char* GetFirstT(const char* p)
{
for ( ; *p; ++p)
{
if ( *p == 't' ) return p;
}

return 0;
}

char* GetFirstT(char* p)
{
return const_cast<char*>( GetFirstT(p) );
}


Why don't you use templates?

template<typename CHARTYPE>
CHARTYPE* GetFirstT(CHARTYPE* p)
{
....
}
--
Regards,
Tobias
Jul 22 '05 #3

P: n/a
JKop wrote:
Here's two functions, a "const version" and a "non-const version":
char* GetFirstT(char* p)
{
for ( ; *p; ++p)
{
if ( *p == 't' ) return p;
}

return 0;
}

const char* GetFirstT(const char* p)
{
for ( ; *p; ++p)
{
if ( *p == 't' ) return p;
}

return 0;
}

signed main()
{
char the_alphabet[] = "abcdefghijklmnopqrstuvwxyz";

char* p_t = GetFirstT(the_alphabet);
}
See how I have to define two functions, is there any handy around that?
Would I have to do the following:

const char* GetFirstT(const char* p)
{
for ( ; *p; ++p)
{
if ( *p == 't' ) return p;
}

return 0;
}

char* GetFirstT(char* p)
{
return const_cast<char*>( GetFirstT(p) );
}
-JKop


Hello,

what about using template?

template <class charT>
charT* GetFirstT(charT* p)
{
for ( ; *p; ++p)
{
if ( *p == 't' ) return p;
}
return 0;
}

signed main()
{
char the_alphabet[] = "abcdefghijklmnopqrstuvwxyz";

char* p_t = GetFirstT<char>(the_alphabet);
}

This way you can create GetFirstT() even for wchar and const wchar. Even
better would force use of character_traits, but this is too much for me.
Maybe someone else will know...

Ales
Jul 22 '05 #4

P: n/a
AlesD wrote:

Hello,

what about using template?

Templates aren't appropriate here.
template <class charT>
charT* GetFirstT(charT* p)
{
for ( ; *p; ++p)
{
if ( *p == 't' ) return p;
}
return 0;
}

signed main()
{
char the_alphabet[] = "abcdefghijklmnopqrstuvwxyz";

char* p_t = GetFirstT<char>(the_alphabet);
}

This way you can create GetFirstT() even for wchar and const wchar.


Well, you'd get code that compiles and runs. But what does *p == 't'
tell you when the type of p is wchar_t*? There is no requirement that
L't' == 't'.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 22 '05 #5

P: n/a
Tobias GŁntner posted:
JKop wrote:
See how I have to define two functions, is there any handy around that? Would I have to do the following:

const char* GetFirstT(const char* p)
{
for ( ; *p; ++p)
{
if ( *p == 't' ) return p;
}

return 0;
}

char* GetFirstT(char* p)
{
return const_cast<char*>( GetFirstT(p) ); }


Why don't you use templates?

template<typename CHARTYPE>
CHARTYPE* GetFirstT(CHARTYPE* p)
{
...
}

That template is non-const.
-JKop

Jul 22 '05 #6

P: n/a

Just to elaborate more on that. While this function doesn't edit any
objects; if possible I want to be able to return a non-const pointer, as the
user may want to then use it for something.

I'm looking for using the same body of code for multiple functions. Like
imagine something like this:

body Blah
{
//code
}

char* FuncName(char*)
using body Blah;

const char* FunctName2(const char*)
using body Blah;
Looks like I've only got two options: either copy and paste and actually
make two functions. The only pickle I have with this is maintaining two
functions, plus added compile time.

Who here would go with the const_cast version?
-JKop

-JKop
Jul 22 '05 #7

P: n/a
"JKop" <NU**@NULL.NULL> wrote in message
news:xj******************@news.indigo.ie...
<snip>
I'm looking for using the same body of code for multiple functions. Like
imagine something like this:

body Blah
{
//code
}

char* FuncName(char*)
using body Blah;

const char* FunctName2(const char*)
using body Blah;
Looks like I've only got two options: either copy and paste and actually
make two functions. The only pickle I have with this is maintaining two
functions, plus added compile time.

Who here would go with the const_cast version?


I've done it before, and I would do it again. I don't know of anything that
would cause problems when using that technique.

--
David Hilsee
Jul 22 '05 #8

P: n/a
JKop <NU**@NULL.NULL> wrote in news:xj******************@news.indigo.ie:

Just to elaborate more on that. While this function doesn't edit any
objects; if possible I want to be able to return a non-const pointer,
as the user may want to then use it for something.


Then you should provide a non-const copy of the object in question, so
there would be no risk of blowing things up.

'const' is there to help keep programs correct. Either use it, or lose it.

--
:: bartekd / o2 pl
:: "out of confusion comes chaos -- out of chaos comes confusion and fear
:: -- then comes lunch."

Jul 22 '05 #9

P: n/a
JKop wrote:
Tobias GŁntner posted:

template<typename CHARTYPE>
CHARTYPE* GetFirstT(CHARTYPE* p)
{
...
}

That template is non-const.


CHARTYPE can be 'char' or 'const char', depending on the parameter type.
--
Regards,
Tobias
Jul 22 '05 #10

P: n/a
JKop <NU**@NULL.NULL> wrote:
Here's two functions, a "const version" and a "non-const version":

char* GetFirstT(char* p)
{
for ( ; *p; ++p)
if ( *p == 't' ) return p;
return 0;
}

const char* GetFirstT(const char* p)
{
for ( ; *p; ++p)
if ( *p == 't' ) return p;
return 0;
} See how I have to define two functions, is there any handy around that?


The C standard library solves this problem with:

char *strchr(const char *ptr, char ch);

ie. using 'const' in the parameter and non-const in the return type.
This 'minimises the damage', ie. you only have to use casts
(when calling the function I mean, not when implementing it) if
you use it on a const string and assign the result to a 'const char *'.

But since this is C++ we can use a template:

template<typename Iter>
Iter GetFirstT(Iter p)
{
for ( ; ; ++p )
if (*p == 't' || *p == '\0')
return p;
}

Constraints - 'Iter' must be a type for which '++', '==' with a char,
and '*' are valid operations.

Note that I have made a slight change, it returns a pointer to the end
of the string instead of NULL if the 't' is not found. But you could
easily stick to your version, but add the constraint that 'Iter'
must be such that it can have 0 assigned to it.

There have been a couple of objections to this approach raised in
this thread, which I don't understand...

You said "the template is non-const". But it does not make sense
to say that a template is const or not, so I have no idea what you
meant. Are you unaware that you can have GetFirstT<char *> and
GetFirstT<char const *> ?

Pete Becker said "GetFirstT<wchar_t *>" doesn't work. So what?
The original stipulation was only for "char *" and "char const *",
and this example does just fine for them. There are plenty
of examples in the standard library where templates won't work
if you use the wrong types as parameters.
Jul 22 '05 #11

P: n/a
Tobias GŁntner posted:
JKop wrote:
Tobias GŁntner posted:

template<typename CHARTYPE>
CHARTYPE* GetFirstT(CHARTYPE* p)
{
...
}

That template is non-const.


CHARTYPE can be 'char' or 'const char', depending on the

parameter type.


No it cannot. CHARTYPE refers to the 'char'.

For a const template:

template<class T>
void Blah(const T)
{

}
-JKop
Jul 22 '05 #12

P: n/a
JKop wrote:
CHARTYPE can be 'char' or 'const char', depending on the
parameter type.


No it cannot.


Yes, it can.
What makes you think it cannot?
CHARTYPE refers to the 'char'.
CHARTYPE refers to the type the pointer points to. That can be anything,
including const chars.

For a const template:

template<class T>
void Blah(const T)


Now why would you want this one? If you pass a char* here, you have a
const pointer to non-const chars, i.e. you cannot alter the pointer.
--
Regards,
Tobias
Jul 22 '05 #13

P: n/a
Tobias GŁntner posted:
JKop wrote:
CHARTYPE can be 'char' or 'const char', depending on the
parameter type.


No it cannot.


Yes, it can.
What makes you think it cannot?
CHARTYPE refers to the 'char'.


CHARTYPE refers to the type the pointer points to. That

can be anything, including const chars.

For a const template:

template<class T>
void Blah(const T)
Now why would you want this one? If you pass a char*

here, you have a const pointer to non-const chars, i.e. you cannot alter the pointer.


You're right.

But still I want to restrict it to either being char* or
const char*.
-JKop

Jul 22 '05 #14

P: n/a
JKop <NU**@NULL.NULL> wrote in message news:<i9******************@news.indigo.ie>...
Here's two functions, a "const version" and a "non-const version":
[snip - two similar implementations] const char* GetFirstT(const char* p)
{
for ( ; *p; ++p)
{
if ( *p == 't' ) return p;
}
return 0;
} char* GetFirstT(char* p)
{
return const_cast<char*>( GetFirstT(p) );
}


This is reasonable, especially if the second is inlined and the first
is not. However, it doesn't make a lot of sense that you would have a
non-const version of this particular function.

/david
Jul 22 '05 #15

This discussion thread is closed

Replies have been disabled for this discussion.