This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: More test results...
- From: Benjamin Kosnik <bkoz at redhat dot com>
- To: libstdc++ at gcc dot gnu dot org, stephen dot webb at bregmasoft dot com
- Date: Thu, 7 Mar 2002 23:17:42 -0800
- Subject: Re: More test results...
> xxx1.o(.bss+0x68): multiple definition of
> `std::numeric_limits<std::basic_string<char, std::char_traits<char>,
> std::allocator<char> > >::is_integer'
Hmm. This isn't a specialization in <limits>, at least
numeric_limits<string> is not one I'm familiar with...
Here's what I've done to reproduce this:
cat > 1.cc
#include <limits>
#include <string>
void foo1()
{
bool b1 = std::numeric_limits<std::string>::is_integer;
bool b2 = std::numeric_limits<int>::is_integer;
}
cat > 2.cc
#include <limits>
#include <string>
void foo2()
{
bool b1 = std::numeric_limits<std::string>::is_integer;
bool b2 = std::numeric_limits<int>::is_integer;
}
cat > 3.cc
extern void foo1();
extern void foo2();
int main()
{
foo1();
foo2();
}
Then
%g++ 1.cc 2.cc 3.cc
/tmp/ccVwNcTu.o(.bss+0x0): multiple definition of `std::numeric_limits<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::is_integer'
/tmp/ccrSXPkE.o(.bss+0x0): first defined here
collect2: ld returned 1 exit status
Which is a major bummer.
%nm 1.o 2.o
1.o:
00000000 T _Z4foo1v
00000000 B _ZNSt14numeric_limitsISsE10is_integerE
00000004 C _ZNSt17_Swap_lock_structILi0EE12_S_swap_lockE
2.o:
00000000 T _Z4foo2v
00000000 B _ZNSt14numeric_limitsISsE10is_integerE
00000004 C _ZNSt17_Swap_lock_structILi0EE12_S_swap_lockE
Seems sane.
It looks like the best approach would be to use a base class for this
data. Here's a patch that does that: we'll have to wait for Gaby's ok
to check it in.
-benjamin
2002-03-08 Benjamin Kosnik <bkoz@redhat.com>
* include/std/std_limits.h: Move static const data members out of
generic template, into base class __numeric_limits_base.
Index: include/std/std_limits.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/std/std_limits.h,v
retrieving revision 1.3
diff -c -p -r1.3 std_limits.h
*** std_limits.h 2002/01/28 22:13:10 1.3
--- std_limits.h 2002/03/08 07:15:33
*************** namespace std
*** 908,1047 ****
//
// The primary class traits
//
template<typename _Tp>
! struct numeric_limits
{
- static const bool is_specialized = false;
-
static _Tp min() throw() { return static_cast<_Tp>(0); }
static _Tp max() throw() { return static_cast<_Tp>(0); }
-
- static const int digits = 0;
- static const int digits10 = 0;
- static const bool is_signed = false;
- static const bool is_integer = false;
- static const bool is_exact = false;
- static const int radix = 0;
-
static _Tp epsilon() throw() { return static_cast<_Tp>(0); }
static _Tp round_error() throw() { return static_cast<_Tp>(0); }
-
- static const int min_exponent = 0;
- static const int min_exponent10 = 0;
- static const int max_exponent = 0;
- static const int max_exponent10 = 0;
-
- static const bool has_infinity = false;
- static const bool has_quiet_NaN = false;
- static const bool has_signaling_NaN = false;
- static const float_denorm_style has_denorm = denorm_absent;
- static const bool has_denorm_loss = false;
-
static _Tp infinity() throw() { return static_cast<_Tp>(0); }
static _Tp quiet_NaN() throw() { return static_cast<_Tp>(0); }
static _Tp signaling_NaN() throw() { return static_cast<_Tp>(0); }
static _Tp denorm_min() throw() { return static_cast<_Tp>(0); }
-
- static const bool is_iec559 = false;
- static const bool is_bounded = false;
- static const bool is_modulo = false;
-
- static const bool traps = false;
- static const bool tinyness_before = false;
- static const float_round_style round_style = round_toward_zero;
};
- template<typename _Tp>
- const bool
- numeric_limits<_Tp>::is_specialized;
-
- template<typename _Tp>
- const int
- numeric_limits<_Tp>::digits;
-
- template<typename _Tp>
- const int
- numeric_limits<_Tp>::digits10;
-
- template<typename _Tp>
- const bool
- numeric_limits<_Tp>::is_signed;
-
- template<typename _Tp>
- const bool
- numeric_limits<_Tp>::is_integer;
-
- template<typename _Tp>
- const bool
- numeric_limits<_Tp>::is_exact;
-
- template<typename _Tp>
- const int
- numeric_limits<_Tp>::radix;
-
- template<typename _Tp>
- const int
- numeric_limits<_Tp>::min_exponent;
-
- template<typename _Tp>
- const int
- numeric_limits<_Tp>::min_exponent10;
-
- template<typename _Tp>
- const int
- numeric_limits<_Tp>::max_exponent;
-
- template<typename _Tp>
- const int
- numeric_limits<_Tp>::max_exponent10;
-
- template<typename _Tp>
- const bool
- numeric_limits<_Tp>::has_infinity;
-
- template<typename _Tp>
- const bool
- numeric_limits<_Tp>::has_quiet_NaN;
-
- template<typename _Tp>
- const bool
- numeric_limits<_Tp>::has_signaling_NaN;
-
- template<typename _Tp>
- const float_denorm_style
- numeric_limits<_Tp>::has_denorm;
-
- template<typename _Tp>
- const bool
- numeric_limits<_Tp>::has_denorm_loss;
-
- template<typename _Tp>
- const bool
- numeric_limits<_Tp>::is_iec559;
-
- template<typename _Tp>
- const bool
- numeric_limits<_Tp>::is_bounded;
-
- template<typename _Tp>
- const bool
- numeric_limits<_Tp>::is_modulo;
-
- template<typename _Tp>
- const bool
- numeric_limits<_Tp>::traps;
-
- template<typename _Tp>
- const bool
- numeric_limits<_Tp>::tinyness_before;
-
- template<typename _Tp>
- const float_round_style
- numeric_limits<_Tp>::round_style;
-
// Now there follow 15 explicit specializations. Yes, 15. Make sure
! // you get the count right.
!
template<>
struct numeric_limits<bool>
{
--- 908,959 ----
//
// The primary class traits
//
+ struct __numeric_limits_base
+ {
+ static const bool is_specialized = false;
+
+ static const int digits = 0;
+ static const int digits10 = 0;
+ static const bool is_signed = false;
+ static const bool is_integer = false;
+ static const bool is_exact = false;
+ static const int radix = 0;
+
+ static const int min_exponent = 0;
+ static const int min_exponent10 = 0;
+ static const int max_exponent = 0;
+ static const int max_exponent10 = 0;
+
+ static const bool has_infinity = false;
+ static const bool has_quiet_NaN = false;
+ static const bool has_signaling_NaN = false;
+ static const float_denorm_style has_denorm = denorm_absent;
+ static const bool has_denorm_loss = false;
+
+ static const bool is_iec559 = false;
+ static const bool is_bounded = false;
+ static const bool is_modulo = false;
+
+ static const bool traps = false;
+ static const bool tinyness_before = false;
+ static const float_round_style round_style = round_toward_zero;
+ };
+
template<typename _Tp>
! struct numeric_limits : public __numeric_limits_base
{
static _Tp min() throw() { return static_cast<_Tp>(0); }
static _Tp max() throw() { return static_cast<_Tp>(0); }
static _Tp epsilon() throw() { return static_cast<_Tp>(0); }
static _Tp round_error() throw() { return static_cast<_Tp>(0); }
static _Tp infinity() throw() { return static_cast<_Tp>(0); }
static _Tp quiet_NaN() throw() { return static_cast<_Tp>(0); }
static _Tp signaling_NaN() throw() { return static_cast<_Tp>(0); }
static _Tp denorm_min() throw() { return static_cast<_Tp>(0); }
};
// Now there follow 15 explicit specializations. Yes, 15. Make sure
! // you get the count right.
template<>
struct numeric_limits<bool>
{