Mukesh Kapoor, 썬 스튜디오 개발팀
 

썬 C++ 컴파일러는 libCstdlibstlportC++ 표준 라이브러리를 구현하는 두가지의 라이브러리를 제공하고 있습니다.

  • libCstd 는 기본적으로 사용되고 Rogue Wave 의 stdlib 2.1.1 에 기반을 두고 있습니다.
  • libstlport는 STLport 버젼 4.5.3 에 기반을 두고 있으며, 컴파일러 옵션 -library=stlport4을 명시함으로써 사용될 수 있습니다.
이 글은 두가지 라이브러리의 차이점과 어떠한 상황에서 어떠한 라이브러리가 사용되는게 더 올바른지에 대해 알아 봅니다.


배경지식

썬 C++ 컴파일러는 1998년 12월에 배포된 C++ 5.0 에 표준 C++ 라이브러리인 libCstd 과 함께 탑재되기 시작하였습니다. 이 때는 멤버 템플릿 클래스, 멤버 함수 템플릿,부분적 특수 기능 등 좀 더 새로운 언어 특성들은 C++ 표준 라이브러리에서는 사용하고 있었음에도 컴파일러에는 아직 구현되기 전이었습니다.libCstd 헤더는 매크로를 사용해서 라이브러리 내의 이러한 특성들에 의존하고 있는 기능을 활성화 혹은 비활성화하였고, 이 매크로들은 새로운 언어 특성을 사용하는 기능을 비활성화하도록 정의되어 있었습니다.

그 다음 버전의 컴파일러에서는 새로운 언어 특성들을 구현 가능하였습니다. 그러나 기존의 오브젝트 파일과의 바이너리 호환성을 유지 하기 위해libCstd 헤더에 있는 매크로 들은 수정되지 않았으며, 결과적으로 최신 버전의 libCstd에는 여전히 몇가지 기능들이 빠져 있었으며, 몇몇 기능은 표준에 정의 되어 있는 것과는 다른 독립 변수들을 받게 되었습니다.

The libstlport 라이브러리는 C++ 5.4 버전에서 처음 소개 되었고 라이브러리에 필요한 언어 특성들을 모두 사용하고 있습니다. 제외된 언어 특성이 없으므로 라이브러리의 어떠한 기능도 축소 되지 않았습니다. 결과적으로 libstlport 라이브러리는 libCstd 보다 좀 더 표준에 가깝게 만들어졌습니다.

libCstd 에서 비활성화 된 언어 기능

이번 문단에서는 libCstd 에서 비활성화된 언어 특성들을 목록화하고 그에 대응하는 기능들에 대해 설명합니다. 간단한 테스트 예제를 통해 존재 하지 않는 기능들을 보여줍니다. 컴파일러는 각 테스트 케이스에서 디폴트값으로 libCstd 이 사용되는 경우 에러를 나타냅니다. 모든 테스트 케이스는 -library=stlport4 컴파일러 옵션을 명시해 줬을때 아무런 문제 없이 컴파일 됩니다. libCstd 에 존재하는 기능을 사용할 경우의 문제 해결 방법이 존재 할 경우 기본적으로 사용자에게 방법이 제공 됩니다.

주의: libCstd 헤더에 정의된 다음의 매크로들은 stdcomp.h 를 이용해 기능을 비활성화합니다.

  • _RWSTD_NO_MEMBER_TEMPLATES
  • _RWSTD_NO_TEMPLATE_ON_RETURN_TYPE
  • _RWSTD_NO_MEM_CLASS_TEMPLATES
  • _RWSTD_NO_CLASS_PARTIAL_SPEC

_RWSTD 로 시작하는 어떠한 매크로의 이름도 재정의(redefine)하지 마시기 바랍니다. 재정의 할 경우 프로그램이 컴파일 되지 않거나, 링크가 되지 않거나 혹은 올바르게 동작하지 않을 수 있습니다. 이러한 문제의 이유는 유저 프로그램에서 바라 보는 헤더 파일은 반드시 프로그램에 링크된 libCstd 를 빌드 하는데 사용된 헤더와 일치해야 하기 때문입니다. 매크로를 재정의 함으로써 라이브러리를 빌드한 방법과 사용되는 방법간에 일관성을 망칠 수 있
습니다.

언어 특성: 멤버 함수 템플릿

_RWSTD_NO_MEMBER_TEMPLATES 매크로는 libCstd 에 정의되어 멤머 템플릿 함수가 지원되지 않음을 나타 내며 매크로 _RWSTD_NO_TEMPLATE_ON_RETURN_TYPE 은 컴파일러가 리턴 타입에 의해 템플릿화 되는 함수의 구문을 지원하지 않음을 나타 냅니다. 결과적으로 다음의 함수들은 사용할 수 없습니다.

<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>&);

예제

다음의 테스트 케이스는 libCstd로 컴파일 되지 않습니다.

 % cat c1.c
#include <complex>
using namespace std;

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

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

% 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
%

해결방법

다음의 라인을

 complex<X> d3;
d3 = d1;
d3 += d2;
아래의 라인으로 변경합니다
 complex<double> temp = d1;
temp += d2;
complex<X> d3(temp.real(), temp.imag());

<string>내의 basic_string 클래스에서 사용할 수 없는 멤버

아래의 리스트에서 Typint, unsigned int, long, unsigned long, short, unsigned short, char, unsigned char, wchar_t, or bool 중 하나가 될 수 있습니다. Typ 를 포함하고 있는 엔트리는 차례대로 각각의 타입에 의해 교체됨으로써 실제로 10 가지 정도의 엔트리가 될 수 있습니다.

  • 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);

예제

 % 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() );
}

% 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.

해결 방법

다음의 라인을

 string s2 = s1.append( l1.begin(), l1.end() );
아래의 라인으로 변경합니다
 string s2(s1);
for( list<char>::iterator i = l1.begin(); i != l1.end(); ++i )
s2 += *i;

<utility>내의 pair 클래스에서 사용할 수 없는 멤버

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

예제

 % cat p1.c
#include <utility>

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

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

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

해결방법

다음의 라인을

 std::pair<S, int> p2 = p1;
아래의 라인으로 교체합니다
 std::pair<S, int> p2(p1.first, p1.second);

<locale>내의 locale 클래스에서 사용할 수 없는 멤버

  •  // 다른 로케일을 기반으로 새로운 로케일을 생성:
    template <class Facet> locale (const locale& other,Facet* f);
  •  // 지정:
    template <class Facet> locale combine(const locale& other);
  •  // 문자열 정렬:
    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 접근:
    template <class Facet> const Facet& use_facet (const locale&);
    template <class Facet> inline bool has_facet (const locale&) throw();

예제

 % cat l1.c
#include <locale>
using namespace std;

main()
{
locale loc1("C");
locale loc2("de");
locale loc3 = loc1.combine<numpunct<char> >(loc2);
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.

<memory> 내의 auto_ptr 클래스에서 사용할 수 없는 멤버

  • template <class Y> operator auto_ptr_ref<Y>();
  • template <class Y> operator auto_ptr<Y>();
  • template <class Y>
      auto_ptr(auto_ptr<Y>&);
  • template <class T>
      inline pair<T*, ptrdiff_t> get_temporary_buffer (ptrdiff_t len);

예제

 % cat a1.c
#include <memory>

struct A {};
struct B : public A {};

main()
{
std::auto_ptr<B> b(new B);
std::auto_ptr<A> a(b);
}

% CC a1.c
"a1.c", line 9: Error: Cannot use std::auto_ptr<B>
to initialize std::auto_ptr<A>.
1 Error(s) detected.

<bitset> 내의 bit_set클래스에서 사용할 수 없는 멤버

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

예제

 % 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> >();
cout << "s = " << s << endl;
}

% CC b1.c
"b1.c", line 8: Error: Badly formed expression.
"b1.c", line 8: Error: "char_traits" cannot be declared as an object or function.
"b1.c", line 8: Error: "allocator" cannot be declared as an object or function.
"b1.c", line 8: Error: "," expected instead of ">".
4 Error(s) detected.

해결방법

다음의 라인을

 string s = b.to_string<char, char_traits<char>, allocator<char> >(); 
아래의 라인으로 교체 합니다
 string s = b.to_string();.


언어 기능: 멤버 템플릿 클래스

매크로 _RWSTD_NO_MEM_CLASS_TEMPLATES 는 컴파일러가 멤버 템플릿 클래스를 지원하지 않음을 나타내기 의해 정의 됩니다. 결과적으로 다음의 클래스들과 생성자들은 <memory>에 정의 되어 있지 않습니다:
  • template <class Y> class auto_ptr_ref{};
  • auto_ptr(auto_ptr_ref<X>&);

예제

 % cat a2.c
#include <memory>
using namespace std;

class A {};
class B : public A {};

main()
{
auto_ptr_ref<A>(auto_ptr<B>::*pf)() =
&auto_ptr<B>:: operator auto_ptr_ref<A>;
}

% CC a2.c
"a2.c", line 9: Error: auto_ptr_ref is not defined.
"a2.c", line 9: Error: Unexpected type name "A" encountered.
"a2.c", line 9: Error: Identifier expected instead of "*".
"a2.c", line 9: Error: pf is not defined.
"a2.c", line 10: Error: An overloadable operator was expected
instead of "auto_ptr_ref".
"a2.c", line 10: Error: auto_ptr_ref is not a member of std::auto_ptr<B>.
"a2.c", line 10: Error: Unexpected type name "A" encountered.
"a2.c", line 10: Error: Operand expected instead of ";".
8 Error(s) detected.


언어 특성: 부분적인 특수 기능

매크로 _RWSTD_NO_CLASS_PARTIAL_SPEC 는 컴파일러가 기본적인 파라미터를 가지고 있는 템플릿 클래스들의 부분 특수 기능을 지원하지 않음을 가르키기 위해 정의 됩니다. 결과적으로 다음과 같은 전역 함수들이 <algorithm>내에 정의되어 있지 않습니다.
  • count()
  • count_if()

예제

 % cat c2.c
#include <algorithm>
#include <list>
#include <iostream>
#include <iterator>
using namespace std;

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

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);
// # elements with value 6
int n2 = count_if(x.begin(), x.end(), gtr3);
// # elements with value >3

cout << "n1 = " << n1 << endl;
cout << "n2 = " << n2 << endl;
}

% CC c2.c
"c2.c", line 23: 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 24: 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.

해결방법

다음의 라인을

 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
아래의 라인으로 교체합니다
 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

<iterator>에서 사용할 수 없는 템플릿 클래스

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

예제

 % cat i1.c
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

main()
{
vector<int> v(10);

for (int i = 0; i < 10; i++)
v[i] = i;

iterator_traits<int>::value_type x = v[5];
cout << "vector: ";
copy (v.begin(), v.end(), ostream_iterator<int>(cout, " "));
cout << endl;
cout << "x = " << x << endl;
}

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

해결방법

다음의 라인을

 iterator_traits<int>::value_type x = v[5];
아래와 같이 교체합니다
 int x = v[5];


어떠한 라이브러리를 사용해야 합니까?

썬 C++ 컴파일러는 libCstd 를 디폴트값으로 사용합니다. 만약 기존에 존재하는 오브젝트 파일과의 바이너리 호환성이 요구되거나 어플리케이션이 libCstd 를 이용해서 빌드된 서로 다른 라이브러리 들과 링크 된다면 어플리케이션을 빌딩 하는데에는 반드시 libCstd가 사용되어야 합니다. 약점이라면 libCstd 에서 사용할 수 없는 특성들은 어플리케이션에서도 사용 할 수 없다는 것입니다.

libstlport 는 표준에 가장 가까운 구현을 제공 합니다. 만약 어플리케이션에 libCstd 에서 제공되지 않는 기능이 필요하다면 libstlport 가 사용 될 수 있습니다. 그러나 이 때 주의할 점은 libCstd libstlport 는 같은 어플리케이션에 사용될 수 없다는 것입니다. 만약 어플리케이션이 -library=stlport4 를 이용해 빌드 되었다면 어플리케이션이 링크되어있고 C++ 라이브러리 함수들을 이용하는 모든 라이브러리들은 반드시 -library=stlport4 를 이용해 컴파일 되어야 합니다. 이는 만약 써드 파티 라이브러리가 사용될 경우에는 가능하지 않을 수도 있습니다. 사용자는 반드시 써드 파티 벤더에게 -library=stlport4 를 이용해 빌드된 라이브러리를 요구해야 합니다.

libstlport 을 사용하는 또 다른 이유는 좀 더 낳은 성능을 위해서 입니다. libstlport의 몇몇 클래스들은 libCstd 에 비해서 좀더 좋은 성능을 가지고 있습니다. 어플리케이션의 성능은 여러가지 요인에 따라 달라지기 때문에 두가지 라이브러리를 모두 사용해 보고 성능을 측정하여 그 결과에 맞게 라이브러리를 사용하는 것이 가장 좋은 방법입니다.

요약

  • libCstd 는 표준 라이브러리의 모든 기능을 지원해 주지 않습니다.
  • libstlport 는 C++ 표준에 좀더 가깝게 만들어 졌습니다.
  • 만약 기존의 오브젝트 파일과 바이너리 호환성을 가지길 원한다면 libCstd 를 사용하시기 바랍니다.
  • 만약 어플리케이션이 libCstd에 없는 기능을 사용하고자 한다면 libstlport 를 사용하시기 바랍니다.
  • 몇몇 케이스에서 libstlport 는 좀더 낳은 성능을 제공 할 수도 있습니다.

"개발자코너" 카테고리의 다른 글

2006/07/23 14:39 2006/07/23 14:39

TRACKBACK :: http://blog.sdnkorea.com/blog/trackback/118

댓글을 달아 주세요

  1. 박정숙  수정/삭제  댓글쓰기

    좋은 정보 감사해요~

    2007/09/19 04:19
[로그인][오픈아이디란?]

◀ Prev 1  ... 548 549 550 551 552 553 554 555 556  ... 806  Next ▶