Board index » cppbuilder » basic_string <unsigned char> linker problem!

basic_string <unsigned char> linker problem!


2007-04-13 05:54:00 AM
cppbuilder31
Hello gurus;)
I need to recompile the id3lib from sourceforge.net v3.8.3 and I'm seems to
be stuck on a linking issue, check this code:
namespace dami
{
typedef std::string String;
typedef std::wstring WString;
typedef std::basic_string <unsigned char>BString;
}
__fastcall TfrmMain::TfrmMain(TComponent* Owner)
: TForm(Owner)
{
dami::BString test;
}
The String and WString works fine, but the BString does not link correctly:
Linker error:
Unresolved external 'std::basic_string<unsigned char,
std::char_traits<unsigned char>, std::allocator<unsigned char>>::__nullref'
Any one who knows if there are already made basic_string support with
<unsigned char>as definitions in Borland C++ Builder>=5?
Thanks.
 
 

Re:basic_string <unsigned char> linker problem!

"Arne-Thomas Aas" < XXXX@XXXXX.COM >wrote in message
Quote
Unresolved external 'std::basic_string<unsigned char,
std::char_traits<unsigned char>, std::allocator<unsigned char>
::__nullref'
You did not say which version of BCB and which STL library you are
using. Using RogueWave in BCB 5, I was able to reproduce the same
error, though.
Adding _RWSTD_COMPILE_INSTANTIATE to the Conditionals list in the
Project Options, or at least using #define _RWSTD_COMPILE_INSTANTIATE
in code before #include <string>, clears the error.
Gambit
 

Re:basic_string <unsigned char> linker problem!

Quote
Adding _RWSTD_COMPILE_INSTANTIATE to the Conditionals list in the
Project Options, or at least using #define _RWSTD_COMPILE_INSTANTIATE
in code before #include <string>, clears the error.


Gambit
Thanks a bunch;
I'm using BCB 5 and it seems that the id3lib uses RW lib, I can se files are
included from that directory after building the lib. Defining
_RWSTD_COMPILE_INSTANTIATE solved the linking issue. Now I can run my vcl
program. But when I create a instance of ID3_Tag from id3lib I get an
runtime error from "cc3250mt.dll" with read of address ABABABC3. I need to
debug the id3lib. This lib proj have I converted with Visual C++ Conversion
Utility. Any idea on this (before I get started on the debug)?
Thanks again!
ATS
 

{smallsort}

Re:basic_string <unsigned char> linker problem!

"Arne-Thomas Aas" < XXXX@XXXXX.COM >writes:
Quote
namespace dami
{
typedef std::string String;
typedef std::wstring WString;
typedef std::basic_string <unsigned char>BString;
}
For the record: specializing std::basic_string for anything other than
char, wchar_t (both provided by the C++ implementation) or a
user-defined type is a bad idea when portability is important (and for
a library hosted by sourceforge, portability *is* important).
The reason is that each specialization std::basic_string<T>relies on
the corresponding specialization std::char_traits<T>; but a C++
implementation is only required to provide std::char_traits
specializations for char and wchar_t.
This means that specializing std::basic_string for char and wchar_t
works out of the box. And specializations for a user-defined character
type can be made to work if the user provides a working specialization
of std::char_traits.
Since we mere users are not allowed to provide a specialization of
std::char_traits for, say, unsigned char, though,
std::basic_string<unsigned char>can't be used portably.
 

Re:basic_string <unsigned char> linker problem!

"Thomas Maeder [TeamB]" < XXXX@XXXXX.COM >wrote in message
Quote
we mere users are not allowed to provide a specialization
of std::char_traits for, say, unsigned char, though
Why is that? Wouldn't it be treated as a user-dsefined type?
Gambit
 

Re:basic_string <unsigned char> linker problem!

"Remy Lebeau \(TeamB\)" < XXXX@XXXXX.COM >writes:
Quote
"Thomas Maeder [TeamB]" < XXXX@XXXXX.COM >wrote in message
news: XXXX@XXXXX.COM ...

>we mere users are not allowed to provide a specialization
>of std::char_traits for, say, unsigned char, though

Why is that? Wouldn't it be treated as a user-dsefined type?
From the standard:
,----[ 17.4.3.1/1 ]
| It is undefined for a C++ program to add declarations or
| definitions to namespace std or to namespaces within namespace std
| unless otherwise specified. A program may add template
| specializations for any standard library template to namespace
| std. Such a specialization (complete or partial) of a standard
| library template results in undefined behavior unless the
| declaration depends on a user-defined name of external linkage and
| unless the specialization meets the standard library requirements
| for the original template.
`----
The problem is specializating std::char_traits<unsigned char>does not
depend on a user defined type, and is therefore an undefined
specialization. It "may" happen to work, but one cannot assume it
will.
--
Chris (TeamB);
 

Re:basic_string <unsigned char> linker problem!

"Chris Uzdavinis (TeamB)" < XXXX@XXXXX.COM >wrote in message
Quote
The problem is specializating std::char_traits<unsigned char>
does not depend on a user defined type, and is therefore an
undefined specialization. It "may" happen to work, but one
cannot assume it will.
Ok, so how about if the app creates a typedef for 'unsigned char' and
makes it into a user-defined type?
Gambit
 

Re:basic_string <unsigned char> linker problem!

"Remy Lebeau \(TeamB\)" < XXXX@XXXXX.COM >writes:
Quote
"Chris Uzdavinis (TeamB)" < XXXX@XXXXX.COM >wrote in message
news: XXXX@XXXXX.COM ...

>The problem is specializating std::char_traits<unsigned char>
>does not depend on a user defined type, and is therefore an
>undefined specialization. It "may" happen to work, but one
>cannot assume it will.

Ok, so how about if the app creates a typedef for 'unsigned char' and
makes it into a user-defined type?
That's one of the funny things about C++: a typedef doesn't define a
type. So, nice try, but no. :)
--
Chris (TeamB);
 

Re:basic_string <unsigned char> linker problem!

Might one design a class which mimics an unsigned char sufficiently to get
around this?
C++ has an odd take on characters, having three, signed char, unsigned char
and char. If I remember correctly that is given but so incompletely
specified that under some circumstances one is unsure to which a plain
'char' would equate.
. Ed
Quote
Chris Uzdavinis wrote in message
news: XXXX@XXXXX.COM ...
>
>>The problem is specializating std::char_traits<unsigned char>
>>does not depend on a user defined type, and is therefore an
>>undefined specialization. It "may" happen to work, but one
>>cannot assume it will.
>
>Ok, so how about if the app creates a typedef for 'unsigned char' and
>makes it into a user-defined type?

That's one of the funny things about C++: a typedef doesn't define a
type. So, nice try, but no. :)
 

Re:basic_string <unsigned char> linker problem!

"Ed Mulroy" < XXXX@XXXXX.COM >writes:
Quote
Might one design a class which mimics an unsigned char sufficiently
to get around this?
?1/1 of the 1998 Standard document requires character types to be POD
types. I think that the following requirements follow:
- no user-declared constructor
- no user-defined copy-assignment operator
- no user-defined destructor
- no non-public non-static data member
- non non-static data member of a non-POD type (my simplification)
- no base class
- no virtual member function
So something like
struct CharType
{
unsigned char rep;
};
should do. In addition, we then need a type that can hold all valid
CharType values plus an end-of-value and a specialization of
std::char_traits.
 

Re:basic_string <unsigned char> linker problem!

Arne-Thomas Aas wrote:
Quote
I'm using BCB 5 and it seems that the id3lib uses RW lib, I can se files are
included from that directory after building the lib. Defining
_RWSTD_COMPILE_INSTANTIATE solved the linking issue. Now I can run my vcl
program. But when I create a instance of ID3_Tag from id3lib I get an
runtime error from "cc3250mt.dll" with read of address ABABABC3. I need to
debug the id3lib. This lib proj have I converted with Visual C++ Conversion
Utility. Any idea on this (before I get started on the debug)?
That is the same problem I had to resolve when I had to use DTL with
bcb5. The real solution is this:
Create a separate cpp (dummy.cpp) file that looks like this:
#ifdef _RTLDLL
#define NEEDCHANGE
#undef _RTLDLL
#endif
#ifdef __BORLANDC__
# ifndef _RWSTD_COMPILE_INSTANTIATE
# define _RWSTD_COMPILE_INSTANTIATE 1
# define __UNDEF_LATER 1
# endif
#endif
#include <string>
#pragma option -Jgd
template class std::basic_string<unsigned char>;
#ifdef __BORLANDC__
# ifdef __UNDEF_LATER
# undef _RWSTD_COMPILE_INSTANTIATE
# undef __UNDEF_LATER
# endif
#endif
#ifdef NEEDCHANGE
#undef NEEDCHANGE
#define _RTLDLL
#endif
Add this file to the id3lib library and (this is important) make sure to
use static multithreaded RTL, not dynamic RTL. This goes both for your
application and id3lib.
 

Re:basic_string <unsigned char> linker problem!

"Ed Mulroy" < XXXX@XXXXX.COM >writes:
Quote
Might one design a class which mimics an unsigned char sufficiently
to get around this?
Probably, but I wouldn't bet that there would be a no abstraction
penalty with BCB's optimizer. In some cases, it may be better to
accept undefined behavior, given that you're aware of the compiler
with which you're using it. (Protected behind some macro guards to
ensure it only is used on tested compilers.)
The template issue and std namespace is problematic for other reasons
too, and some believe that it was an oversight by the committee. For
example, you can specialize std::swap for a user-defined type, but you
cannot overload it for a user-defined type. That's fine for concrete
types, but if you would like an optimized std::swap for a nifty class
template you just wrote, you cannot have it without conveniently
ignoring this proscription. (The resaon is, we'd need a new overload
for std::swap that is a function template, handling myclass<T>for all
types of T.)
The consequences of ignoring this rule, have, to the best of my
knowledge, been non-existant. But for the sake of purity, it's still
wrong. (I would hope that this is addressed in the next standard.)
Quote
C++ has an odd take on characters, having three, signed char, unsigned char
and char. If I remember correctly that is given but so incompletely
specified that under some circumstances one is unsure to which a plain
'char' would equate.
It's true that just "char" is not specified to be signed or unsigned,
but they are distinguishable from "signed char" and "unsigned char" by
C++'s type system. (For example, overload resolution would not be
ambiguous.)
void foo(char);
void foo(unsigned char);
void foo(signed char);
int main()
{
char x;
foo(x);
}
For example, the above code would call foo(char) no matter if that
platform used signed or unsigned implementations for char.
However, if only the explicitly signed and unsigned versions of foo
were provided, then the above code would be ambiguous.
--
Chris (TeamB);
 

Re:basic_string <unsigned char> linker problem!

Chris Uzdavinis (TeamB) < XXXX@XXXXX.COM >wrote:
Quote
For
example, you can specialize std::swap for a user-defined type, but you
cannot overload it for a user-defined type. That's fine for concrete
types, but if you would like an optimized std::swap for a nifty class
template you just wrote, you cannot have it without conveniently
ignoring this proscription. (The resaon is, we'd need a new overload
for std::swap that is a function template, handling myclass<T>for all
types of T.)
This is definitely an area where concepts could come in: provide a swap
method for your class or template, and apply a concept of MemberSwap,
and std::swap could specialise itself to call class::swap() on entities
that exhibit MemberSwap, and the normal old-style version on others.
(Concepts are really nice - they really assist writing templates. With
luck, the slide show from the ACCU Conference should appear soon.
Meanwhile, N2193 may give you some flavour by listing the modifications
required to the standard. MemberSwap is an example concept.)
Alan Bellingham
--
10th Anniversary ACCU Conference: 11-14 April 2007 - Oxford, UK
(Booking now open: see accu.org/index.php/conferences for details)
 

Re:basic_string <unsigned char> linker problem!

Thanks for all replies.
I have tried to digest your discussion the best I can. And I have tired the
previous solution and with no luck. Now I get a different kind of runtime
memory error when I try to open an mp3 file. But my debugging shows that it
still happens in accessing the string functions. When a trace I get several
kind of string implementations files open in my project. I need to go
further with my project so now I am using share ware COM- module, for
accessing the mp3-tags. But I'm still anxious to get the id3Lib from
sourceforge to work. So any one of you gurus still have some energy left on
this topic all replies are truly appreciated.
Thomas.
 

Re:basic_string <unsigned char> linker problem!

Thomas Maeder [TeamB] < XXXX@XXXXX.COM >wrote:
Quote
"Arne-Thomas Aas" < XXXX@XXXXX.COM >writes:

>namespace dami
>{
>typedef std::string String;
>typedef std::wstring WString;
>typedef std::basic_string <unsigned char>BString;
>}

For the record: specializing std::basic_string for anything other than
char, wchar_t (both provided by the C++ implementation) or a
user-defined type is a bad idea when portability is important (and for
a library hosted by sourceforge, portability *is* important).

The reason is that each specialization std::basic_string<T>relies on
the corresponding specialization std::char_traits<T>; but a C++
implementation is only required to provide std::char_traits
specializations for char and wchar_t.

This means that specializing std::basic_string for char and wchar_t
works out of the box. And specializations for a user-defined character
type can be made to work if the user provides a working specialization
of std::char_traits.

Since we mere users are not allowed to provide a specialization of
std::char_traits for, say, unsigned char, though,
std::basic_string<unsigned char>can't be used portably.
I suppose
std::basic_string< unsigned char, my_char_traits<unsigned char>>
would be OK, though?
(Here's a definition of 'my_char_traits' which,
while made implementation-defined through the
'reinterpret_cast<>', seems portable enough for
our needs:
template<class char_type>
struct my_char_traits;
template<>
struct my_char_traits<unsigned char>{
typedef std::char_traits<char>my_base_type;
typedef unsigned char char_type;
typedef my_base_type::int_type int_type;
typedef my_base_type::pos_type pos_type;
typedef my_base_type::off_type off_type;
typedef my_base_type::state_type state_type;
static void assign(char_type& lhs, const char_type& rhs)
{lhs = rhs;}
static bool eq(const char_type& lhs, const char_type& rhs)
{return lhs == rhs;}
static bool lt(const char_type& lhs, const char_type& rhs)
{return lhs < rhs;}
static int compare( const char_type* lhs
, const char_type* rhs
, std::size_t count)
{return my_base_type::compare( reinterpret_cast<const char*>(lhs)
, reinterpret_cast<const char*>(rhs), count );}
static std::size_t length(const char_type *str)
{return my_base_type::length( reinterpret_cast<const char*>(str) );}
static char_type* copy( char_type* lhs
, const char_type* rhs
, std::size_t count )
{return my_base_type::copy( reinterpret_cast< char*>(lhs), count
, reinterpret_cast<const char*>(rhs), count );}
static const char_type* find( const char_type* str
, std::size_t count
, const char_type& ch )
{return my_base_type::find( reinterpret_cast<const char*>(str,count,ch) );}
static char_type* move( char_type* str1
, const char_type* str2
, std::size_t count )
{return my_base_type::move( reinterpret_cast< char*>(str1), count
, reinterpret_cast<const char*>(str2), count );}
static char_type* assign( char_type* str, std::size_t count, char_type ch )
{return my_base_type::assign( reinterpret_cast<char*>(str), count, ch );}
static char_type to_char_type(const int_type& Int)
{return static_cast<char_type>(Int);}
static int_type to_int_type(const char_type& ch)
{return static_cast<int_type>(ch);}
static bool eq_int_type(const int_type& lhs, const int_type& rhs)
{return my_base_type::eq_int_type(lhs,rhs);}
static int_type eof()
{return my_base_type::eof();}
static int_type not_eof(const int_type& _Meta)
{return my_base_type::not_eof();}
};
What do you think?
Schobi
--
XXXX@XXXXX.COM is never read
I'm HSchober at gmx dot org
"My hope is that if more people start reading books,
the world will become a better place."
froarulv in afp