how to avoid reinterpret_cast in this snippet?

A

Alf P. Steinbach

* (e-mail address removed):
Actually it is pretty obvious that std::string has no constructor that
takes unsigned char* as an argument just by looking at its
constructors...none of them take an unsigned char* as an argument. The
fact that you can pass one as an argument to some of these constructors
is a consequence of a language feature, mainly that it will
automatically do some conversions for you. The very important
distinction here is that unsigned char* is being converted to something
else,

No, it isn't.
 
B

Bob Hairgrove

The following
*does* compile:

// test_uchar.cpp

#include <iostream>
#include <ostream>
#include <string>

int main()
{
const unsigned char msg[] = "Hello";
std::string s( msg, msg+5 );
std::cout << s << std::endl;
}

Not on my machine:

Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
test_uchar.cpp:
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
Error: Unresolved external 'std::basic_string<char,
std::char_traits<char>, std::allocator<char> >::basic_string<char,
std::char_traits<char>, std::allocator<char> >(const unsigned char *,
const unsigned char *, const std::allocator<char>&)' referenced from
E:\TEST_UCHAR.OBJ
 
B

Bob Hairgrove

Nope. However, this does:

#include <string>
const unsigned char msg[] = "Hello";
std::string s(msg,msg+sizeof(msg));

Not on my machine:

Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
test_uchar.cpp:
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
Error: Unresolved external 'std::basic_string<char,
std::char_traits<char>, std::allocator<char> >::basic_string<char,
std::char_traits<char>, std::allocator<char> >(const unsigned char *,
const unsigned char *, const std::allocator<char>&)
' referenced from E:\TEST_UCHAR.OBJ
 
B

Bob Hairgrove

The following
*does* compile:

// test_uchar.cpp

#include <iostream>
#include <ostream>
#include <string>

int main()
{
const unsigned char msg[] = "Hello";
std::string s( msg, msg+5 );
std::cout << s << std::endl;
}

Not on my machine:

Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
test_uchar.cpp:
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
Error: Unresolved external 'std::basic_string<char,
std::char_traits<char>, std::allocator<char> >::basic_string<char,
std::char_traits<char>, std::allocator<char> >(const unsigned char *,
const unsigned char *, const std::allocator<char>&)' referenced from
E:\TEST_UCHAR.OBJ

OK -- it compiles, but it doesn't link because Borland provides no
*compiler magic* to make it work.
 
B

Bob Hairgrove

Nope. However, this does:

#include <string>
const unsigned char msg[] = "Hello";
std::string s(msg,msg+sizeof(msg));

Not on my machine:

Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
test_uchar.cpp:
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
Error: Unresolved external 'std::basic_string<char,
std::char_traits<char>, std::allocator<char> >::basic_string<char,
std::char_traits<char>, std::allocator<char> >(const unsigned char *,
const unsigned char *, const std::allocator<char>&)
' referenced from E:\TEST_UCHAR.OBJ

OK -- it compiles, but it doesn't link because Borland provides no
*compiler magic* to make it work.
 
K

Kai-Uwe Bux

Ron said:
There is no coinstructor that takes ONLY an unsigned char* and an
integral value. He passed a unsigned char* and the integer 12.

True, but utterly irrelevant:

May I remind you of the original post:
I have a unsigned char buffer 'buffer[1024]' and I need to convert the
first 12 bytes of it into a string. Below is a code that should work,
however, how can I avoid reinterpret_cast operator?
Or Is there a simple way to get around this?
Thanks.
-KK
/* not tested yet */
typedef unsigned char BYTE
std::string GetStringFromByteBuffer(const BYTE* const buffer, int pos )
{
const char *chAry = reinterpret_cast <const char *> (buffer + pos);
std::string tmp(chAry,12);
return chAry;
}

The operative phrase being "*how* can I avoid...", the OP asks about a way
to implement GetStringFromBuffer that avoids casts. This clearly can be
done using the templated std::string constructor I mentioned. The following
solution is essentially stolen from Alf Steinbach's post:

std::string GetStringFromByteBuffer(const BYTE* const buffer, int pos )
{
return std::string( buffer+pos, buffer+pos+12 );
}

This fits the specs given by the OP. The claim that "there is really no way
to avoid it [casting] if you must pass unsigned char to this function" is
therefore false. The line "Because std::string has no constructor that
takes unsigned char* as an argument" was given as a reason, and since it
tries to argue something false, it is false itself or fails to imply what
it is supposed to argue. Make your pick: if you read it as narrow as

std::string ( unsigned char*, int ) is not valid

then it fails to imply what it is supposed to argue; if you use a broader
reading, the statement will become false.


Best

Kai-Uwe Bux
 
A

Alf P. Steinbach

* Bob Hairgrove:
Nope. However, this does:

#include <string>
const unsigned char msg[] = "Hello";
std::string s(msg,msg+sizeof(msg));

Not on my machine:

Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
test_uchar.cpp:
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
Error: Unresolved external 'std::basic_string<char,
std::char_traits<char>, std::allocator<char> >::basic_string<char,
std::char_traits<char>, std::allocator<char> >(const unsigned char *,
const unsigned char *, const std::allocator<char>&)
' referenced from E:\TEST_UCHAR.OBJ

OK -- it compiles, but it doesn't link because Borland provides no
*compiler magic* to make it work.

Try

bcc32 -D"_RWSTD_COMPILE_INSTANTIATE" -w-ccc -w-rch test_uchar.cpp

Hth.,

- Alf


PS: I recommend using some other free compiler, e.g. g++ or MSVC; <url:
http://home.no.net/dubjai/win32cpptut/html/w32cpptut_01_01_02.html>.
 
O

Old Wolf

Bob said:
#include <string>
const unsigned char msg[] = "Hello";
std::string s(msg,msg+sizeof(msg));

Not on my machine:

Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
test_uchar.cpp:
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
Error: Unresolved external 'std::basic_string<char,
std::char_traits<char>, std::allocator<char> >::basic_string<char,
std::char_traits<char>, std::allocator<char> >(const unsigned char *,
const unsigned char *, const std::allocator<char>&)

That's a bug in the standard library supplied with Borland C++.
The body of the constructor is never defined.
My workaround is to avoid using that constructor.
 
A

Alf P. Steinbach

* Old Wolf:
Bob said:
#include <string>
const unsigned char msg[] = "Hello";
std::string s(msg,msg+sizeof(msg));

Not on my machine:

Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
test_uchar.cpp:
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
Error: Unresolved external 'std::basic_string<char,
std::char_traits<char>, std::allocator<char> >::basic_string<char,
std::char_traits<char>, std::allocator<char> >(const unsigned char *,
const unsigned char *, const std::allocator<char>&)

That's a bug in the standard library supplied with Borland C++.
The body of the constructor is never defined.
My workaround is to avoid using that constructor.

See my reply to the same posting -- the constructor body is defined in
a file that is conditionally included by <string>.

I suspect there is also a way to link a compiled version of that file,
using some language extension (doing the job of 'export'), but, it's an
old compiler, so I don't care to use the time to find out.

Cheers,

- Alf
 
B

Bob Hairgrove

Try

bcc32 -D"_RWSTD_COMPILE_INSTANTIATE" -w-ccc -w-rch test_uchar.cpp

Hth.,

No, it doesn't really "help" (HTH == "hope this helps") <g>

The basic question remains:
Is it *required* by the C++ standard that your code compiles (and
links)? And if you think so, please explain why (and not just: "it
does").

[I hope you realize that the above "hack" can create serious problems
with code that is distributed among different DLLs which rely on
things defined in the DLLs supplied by Borland (e.g., anything even
remotely depending on VCL)?]
 
A

Alf P. Steinbach

* Bob Hairgrove:
No, it doesn't really "help" (HTH == "hope this helps") <g>

The basic question remains:
Is it *required* by the C++ standard that your code compiles (and
links)?

Yes, but not that it "works". The working aspect is covered by
conversion from unsigned char to char (not pointers but values). And
this value conversion, although in-practice well-defined on all modern
platforms, is formally undefined behavior language-wise.

To make more sure that it works, not just compiles and links, one would
have to include a compile time assertion like

static unsigned char const polyanna = 156; // Say.
BOOST_STATIC_ASSERT(
static_cast<unsigned char>( static_cast<char>( polyanna ) ) ==
polyanna
);

And add the assumption that the original data consists of char values
casted to unsigned char -- but I think that borders on the ludicrious.

And if you think so, please explain why (and not just: "it
does").

By definition of the templated std::basic_string constructor, which is
required to copy the values.

[I hope you realize that the above "hack" can create serious problems
with code that is distributed among different DLLs which rely on
things defined in the DLLs supplied by Borland (e.g., anything even
remotely depending on VCL)?]

No, I didn't realize that, and I don't know that, and it isn't a hack,
it's a compiler invocation. It sounds improbable. But, it's an old
compiler and I don't really care about its undocumented features. ;-)

Hth.,

- Alf
 
R

Ron Natalie

Alf said:
* Ron Natalie:

Nope.
There is NO constructor that takes ONLY a unsigned char* (or even
an unsigned char* and a integer like the OP's original intended use).
 
A

Alf P. Steinbach

* Ron Natalie:
There is NO constructor that takes ONLY a unsigned char* (or even
an unsigned char* and a integer like the OP's original intended use).

So?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top