Comparing C++ Standard Libraries libCstd, libstlport, and libstdcxx

by Mukesh Kapoor, May 2006 (updated by Stephen Clamage, June 2016)

This article discusses the differences among three libraries and explores the situations in which one library is preferred over another.

For use in -compat=5 or -std=sun03 mode, the Oracle Developer Studio C++ compiler can make use of any of three implementations of the C++ standard library: libCstd, libstlport, and libstdcxx.

  • libCstd is used by default and is based on Rogue Wave's stdlib 2.1.1.
  • libstlport is based on STLport version 4.5.3 and is used if you specify the compiler option -library=stlport4.
  • libstdcxx is based on the Apache Standard C++ open source library version 4, and is used if you specify the compiler option -library=stdcxx4.

Background

The Oracle Developer Studio C++ compiler started shipping with the standard C++ library libCstd in the C++ 5.0 release of December 1998. Some of the newer language features such as member template classes, member template functions and partial specializations were not yet implemented in the compiler even though the C++ standard library uses all these language features. The libCstd headers use macros to enable or disable functionality in the library that rely on these features and the macros were defined to disable the functionality that uses the missing language features.

Later versions of the compiler implemented the new language features. However, in order to maintain binary compatibility with existing object files, the macros in the libCstd headers were not modified. As a result, the latest version of libCstd continues to have some missing functionality, and some of the functions accept a different set of arguments than those that are specified in the standard.

The libstlport library was introduced in the C++ 5.4 release and uses all the language features needed by the library.

Support for the libstdcxx library was introduced in the C++ 5.10 release, and uses all the language features needed by the library.

No library functionality is suppressed in libstlport or libstdcxx because of missing language features. These libraries, therefore, conform more closely to the standard than does libCstd.

Disabled Language Features in libCstd

This section lists the different language features that are disabled in libCstd along with the corresponding missing functionality. Small test examples illustrate the missing features. The compiler issues errors for each test case if the default libCstd is used. All the test cases compile without errors using libstlport or libstdcxx. Workarounds using the existing libCstd functionality are provided wherever possible.

Note: The following macros defined in the libCstd header stdcomp.h are used to disable functionality:

  • _RWSTD_NO_MEMBER_TEMPLATES
  • _RWSTD_NO_TEMPLATE_ON_RETURN_TYPE
  • _RWSTD_NO_CLASS_PARTIAL_SPEC

Do not redefine any macro whose name starts with _RWSTD, because doing so can result in a program that won't compile, won't link, or won't run correctly. The reason for such problems is that the headers that are seen by a user program must match the headers that were used to build the libCstd that is linked to the program. By redefining the macro, you introduce an inconsistency between the way the library was built and the way it's being used.

Language Feature: Member Function Templates

The macro _RWSTD_NO_MEMBER_TEMPLATES is defined in libCstd to indicate that member template functions are not supported, and the macro _RWSTD_NO_TEMPLATE_ON_RETURN_TYPE is defined to indicate that the compiler does not support the syntax for functions that are templatized only on the return type. As a result, the following functions are missing.

Missing Members of Class complex in <complex>

  • template <class X> complex<T>& operator= (const complex<X>& rhs);
  • template <class X> complex<T>& operator+= (const complex<X>& rhs);
  • template <class X> complex<T>& operator-= (const complex<X>& rhs);
  • template <class X> complex<T>& operator*= (const complex<X>& rhs);
  • template <class X> complex<T>& operator/= (const complex<X>&);

Example

The following test case does not compile with libCstd:

 % cat c1.c

 #include <complex>
 using namespace std;

 struct X {
     X() : d(0.0) { }
     X(double x) : d(x) { }
     X& operator +=(double y) { d += y; return *this; }
     double d;
 };

 int main()
 {
     const complex<double> d1(1.0, 2.0);
     const complex<double> d2(3.0, 4.0);
     complex<X> d3;
     d3 = d1;  // line 16
     d3 += d2; // line 17
 }

 % CC c1.c
 "c1.c", line 15: Error: Cannot assign const std::complex<double> to
 std::complex<X> without "std::complex<X>::operator=(const std::complex<X>&)";.
 "c1.c", line 16: Error: The operation "std::complex<X> += const
 std::complex<double>" is illegal.
 2 Error(s) detected.
 % CC -library=stlport4 c1.c
 %

Workaround

Replace the lines

 complex<X> d3;

 d3 = d1;
 d3 += d2;

with

 complex<double> temp = d1;

 temp += d2;
 complex<X> d3(temp.real(), temp.imag());

Missing Members of Class basic_string in <string>

In the list below, Typ can be one of: int, unsigned int, long, unsigned long, short, unsigned short, char, unsigned char, wchar_t, or bool. An entry containing Typ is actually ten entries with Typ replaced by each of these types in turn.

  • template <class InputIterator> basic_string (InputIterator, InputIterator, const Allocator&);
  • basic_string (Typ n, charT c, const Allocator& alloc);
  • template<class InputIterator> basic_string<charT, traits, Allocator>& append (InputIterator, InputIterator);
  • basic_string<charT, traits, Allocator>& append (Typ n, charT c);
  • template<class InputIterator> basic_string<charT, traits, Allocator>& assign (InputIterator, InputIterator);
  • basic_string<charT, traits, Allocator>& assign (Typ n, charT c);
  • template<class InputIterator> void insert (iterator, InputIterator, InputIterator);
  • void insert (iterator p, Typ n, charT c);
  • template<class InputIterator> basic_string<charT, traits, Allocator>& __replace_aux (iterator first1, iterator last1, InputIterator first2, InputIterator last2);
  • template<class InputIterator> basic_string<charT, traits, Allocator>& replace (iterator, iterator, InputIterator, InputIterator);
  • basic_string<charT, traits, Allocator>& replace (iterator first, iterator last, Typ n, charT c);

Example

 % cat s1.c

 #include <string>
 #include <list>
 using namespace std;

 int main()
 {
     string s1("abcd");
     list<char> l1;
     l1.push_back('e');
     l1.push_back('f');
     string s2 = s1.append( l1.begin(), l1.end() ); // line 11
 }

 % CC s1.c
 "s1.c", line 11: Error: Could not find a match for std::string::append
 (std::list<char>::iterator, std::list<char>::iterator) needed in main().
 1 Error(s) detected.

Workaround

Replace the line

 string s2 = s1.append( l1.begin(), l1.end() );

with

 string s2(s1);

 for( list<char>::iterator i = l1.begin(); i != l1.end(); ++i )
     s2 += *i;

Missing Member of Class pair in <utility>

  • template<class U, class V> pair(const pair<U, V> &p);

Example

 % cat p1.c

 #include <utility>

 struct S {
     S() { val = 0; }
     S(int i) { val = i; }
     int val;
 };

 int main()
 {
     std::pair<int, int> p1(1, 2);
     std::pair<S, int> p2 = p1; // line 12
 }

 % CC p1.c
 "p1.c", line 12: Error: Cannot use std::pair<int, int> to initialize std::pair<S, int>.
 1 Error(s) detected.

Workaround

Replace the line

 std::pair<S, int> p2 = p1;

with

 std::pair<S, int> p2(p1.first, p1.second);

Missing members of class locale in <locale>

  • // creating locale based on other locales:
    template <class Facet> locale (const locale& other,Facet* f);
  • // assignment:
    template <class Facet> locale combine(const locale& other);
  • // sorting of strings:
    template <class charT, class Traits, class Allocator> bool operator() (const basic_string<charT,Traits,Allocator>& s1, const basic_string<charT,Traits,Allocator>& s2) const;
  • // facet access:
    template <class Facet> const Facet& use_facet (const locale&); template <class Facet> inline bool has_facet (const locale&) throw();

Example

 % cat l1.c

 #include <locale>
 using namespace std;

 int main()
 {
 locale loc1("C");
 locale loc2("de");
 locale loc3 = loc1.combine<numpunct<char> >(loc2); // line 8
 const time_get<char>& f = use_facet<time_get<char> >(loc1);
 }

 % CC l1.c
 "l1.c", line 8: Error: Unexpected type name "std::numpunct<char>" encountered.
 "l1.c", line 8: Error: combine is not a member of std::locale.
 "l1.c", line 9: Error: Could not find a match for std::use_facet<std::Facet>
 (std::locale) needed in main().
 3 Error(s) detected.

Missing Members of Class bit_set in <bitset>

  • template <class charT, class traits, class Allocator>
  • basic_string<charT,traits,Allocator> to_string () const;

Example

 % cat b1.c

 #include <bitset>
 #include <iostream>
 using namespace std;
 int main()
 {
     bitset<7> b(4);
     string s = b.to_string<char, char_traits<char>, allocator<char> >(); // line 7
     cout << "s = " << s << endl;
 }
 % CC b1.c
 "b1.c", line 7: Error: Badly formed expression.
 . . .

and possibly additional error messages.

Workaround

Replace the line

string s = b.to_string<char, char_traits<char>, allocator<char> >();

with

string s = b.to_string();.

Language Feature: Partial Specializations

The macro
_RWSTD_NO_CLASS_PARTIAL_SPEC is defined to indicate that the compiler does not support partial specialization of template classes with default parameters. As a result, the following global functions are missing in <algorithm>.

  • count()
  • count_if()

Example

 % cat c2.c

 #include <algorithm>
 #include <list>
 #include <iostream>
 #include <iterator>
 using namespace std;

 bool gtr3(int n)
 {
     return (n > 3);
 }

 int main()
 {
     // count elements in a list
     list<int> x;
     for (int i = 0; i < 10; i++)
	 x.push_back(i);
     cout << "list: ";
     copy (x.begin(), x.end(), ostream_iterator<int>(cout, " "));
     cout << endl;
     int n1 = count(x.begin(), x.end(), 6); // line 21
     int n2 = count_if(x.begin(), x.end(), gtr3); // line 22
     cout << "n1 = " << n1 << endl;
     cout << "n2 = " << n2 << endl;
 }

 % CC c2.c
 "c2.c", line 21: Error: Could not find a match for std::count<std::InputIterator, std::T, std::Size>
 (std::list<int>::iterator, std::list<int>::iterator, int) needed in main().
 "c2.c", line 22: Error: Could not find a match for std::count_if<std::InputIterator, std::Predicate, std::Size>
 (std::list<int>::iterator, std::list<int>::iterator, bool(int)) needed in main().
 2 Error(s) detected.

Workaround

Replace the lines

 int n1 = count(x.begin(), x.end(), 6); // # elements with value 6

 int n2 = count_if(x.begin(), x.end(), gtr3); // # elements with value >3

with

 int n1 = 0;

 int n2 = 0;
 count(x.begin(), x.end(), 6, n1); // # elements with value 6
 count_if(x.begin(), x.end(), gtr3, n2); // # elements with value >3

Missing Template Classes in <iterator>

  • template <class Iterator> struct iterator_traits {}
  • template <class T> struct iterator_traits<T*> {}
  • template <class T> struct iterator_traits<const T*> {}

Example

 % cat i1.c

 #include <iterator>
 #include <vector>
 #include <iostream>
 using namespace std;

 int main()
 {
     vector<int> v(10);
     for (int i = 0; i < 10; i++)
	 v[i] = i;
     iterator_traits<int*>::value_type x = v[5]; // line 11
     cout << "vector: ";
     copy (v.begin(), v.end(), ostream_iterator<int>(cout, " "));
     cout << endl;
     cout << "x = " << x << endl; // line 15
 }

 % CC i1.c
 "i1.c", line 11: Error: iterator_traits is not defined.
 "i1.c", line 11: Error: Badly formed expression.
 "i1.c", line 15: Error: x is not defined.
 3 Error(s) detected.

Workaround

Replace the line

iterator_traits<int>::value_type x = v[5];

with

int x = v[5];

Which Library Should You Use?

Historically, Oracle Developer Studio C++ used libCstd by default. Depending on the compiler and OS version, the default library might be different. If binary compatibility with existing object files or libraries is required, and those object files or libraries were built using libCstd, then libCstd must be used for building the application. The drawback is that the application cannot use the features that are missing in libCstd.

libstlport provides an implementation that is much closer to the standard. If an application needs the functionality that is missing in libCstd, then libstlport can often be used.

Note 1: libstlport does not have support for C++ locales, used for internationalization and localization of text input and output.

Note 2: The shared library libstlport.so.1 must be shipped as part of your application if you choose to use it. Unlike libCstd and libstdcxx, it is not provided as part of Oracle Solaris.

libstdcxx provides a full implementation of the C++ Standard Library, including C++ locales. Ordinarily, this library is the preferred choice.

Note 1: libstdcxx is available only on Oracle Solaris 10 updates 10 and 11, and on Oracle Solaris 11.

Note 2: Support for libstdcxx is not available with compilers older than C++ 5.10.

Additional Considerations

  • The libraries each implement the C++ Standard Library interface, but the internal details are different and incompatible. An entire program, including all libraries linked to it, must be built with the same -library option: one of -library=Cstd (the default), -library=stlport4, or -library=stdcxx4.
  • There are some runtime performance differences among the libraries, but the differences are not easy to characterize. If more than one library choice is available, you could measure the application's performance on typical data sets using different libraries.

Summary

  • libCstd does not support all the features of the standard library.
  • libstlport conforms more closely to the C++ standard, but does not have support for C++ locales.
  • libstdcxx is a complete implementation of the C++ Standard Library.
  • libCstd is provided with all Oracle Solaris versions.
  • libstlport is not provided with Oracle Solaris. You must provide it with your application.
  • libstdcxx cannot be used with compilers earlier than C++ 5.10, and is not available on Oracle Solaris versions earlier than Oracle Solaris 10 update 10.
  • Whichever library you select must be used consistently for all parts of an application, including any libraries linked to it.

References

  1. Nicolai M. Josuttis, The C++ Standard Library, Addison-Wesley, 1999
  2. Bjarne Stroustrup, The C++ Programming Language, Addison-Wesley, 1997