C++ 표준 문서 N2798의 14.3.1의 4번째 항목을 보면. 위와 같은 내용이 있다.
 ( 더 최신 문서인 N3092 에는 위 항목이 빠져 있음. )

 해석을 해서 옮기고 싶지만..
 괜히 혼란만 가중 시킬것 같아서.. 패스하고..

  아무튼 자세히 보면.. 정말 해괴망측한 부분이 있는데
  그 부분을 조금 더 살펴 보자면... 아래와 같은 코드가 있다고 했을 때

    1 template<typename T>

    2 struct X

    3 {

    4     static void f(const T& t)

    5     {

    6         t.a = 100;

    7     }

    8 };

 
 함수 f()는 const로 받은 변수의 값을 변경하고 있다.
 얼핏 보아도 이상한 코드다.
 (  아직 template가 instantiation이 되지 않아서 이 부분만 가지고는 컴파일 에러가 나지 않는다.)


 코드를 조금 더 작성해 보면..

    9 struct S

   10 {

   11     int a;

   12 };

   13 

   14 int main(int argc, char* argv[])

   15 {

   16     S s;

   17     X<S>::f(s);

   18 


이제 아마 Line 17에서 readonly인 a에 값을 넣으려고 했다고 해서 컴파일 에러가 날 것이다.
근데 C++0x 부터는 이를 회피할 수 있는 아주 간단한 방법이 생겼다.
단순히 ' & ' 하나만 추가 하면 된다.


   16     S s;

   17     X<S&>::f(s);

   18 

   19     cout << s.a << endl;


 이제 함수 f()는 
 void X::f(S& t) 와 같이 파라미터의 타입이 정해지고, const 속성을 날려버리게 된다. 우왕ㅋ굳ㅋ
 ( 물론, 이렇게 만들어서 const 속성을 없애서 쓰자는 이야기는 절대 아님...)



 C++의 복잡도는.. 날이 갈 수록 올라가고 있다.


끝으로 Quiz..
각각 파라미터 타입은 어떻게 될까요? ( Line 11 ~ Line 29 )
참고로 gcc 4.5.0과 VS2010 에서 둘다 돌려봤는데. 같게 나왔습니다.

    1 template<typename T>

    2 struct R

    3 {

    4     static void A(T&){}

    5     static void B(const T&){}

    6     static void C(T&&){}

    7     static void D(const T&&){}

    8 };

    9 

   10 {

   11     R<int&>::A(?)

   12     R<int&>::B(?)

   13     R<int&>::C(?)

   14     R<int&>::D(?)

   15 

   16     R<const int&>::A(?)

   17     R<const int&>::B(?)

   18     R<const int&>::C(?)

   19     R<const int&>::D(?)

   20 

   21     R<int&&>::A(?)

   22     R<int&&>::B(?)

   23     R<int&&>::C(?)

   24     R<int&&>::D(?)

   25 

   26     R<const int&&>::A(?)

   27     R<const int&&>::B(?)

   28     R<const int&&>::C(?)

   29     R<const int&&>::D(?)

   30 }



Posted by U∙Seung

r-value reference 쓸려고 테스트를 해봤습니다.


#. 일단 임의의 문자열(string) N개를 vector에 넣고..

    1     static const size_t N = 100000;

    2     static const size_t MaxLen = 100;

    3     static const char range[] = "abcdefghijklmnopqrstuvwxyz_0123456789";

    4 

    5     struct rnd_gen

    6     {

    7         char operator()() const

    8         {

    9             return range[std::rand() % (_countof(range) - 1)];

   10         }

   11     };

   12 

   13     std::vector<std::string> v(N);

   14     for(int i=0; i<N; ++i)

   15     {

   16         std::generate_n(

   17             std::back_inserter(v[i]),

   18             std::rand() % MaxLen + 1, rnd_gen());

   19     }



#. Sorting 해보고

   20     {

   21         boost::timer t;

   22         std::sort(v.begin(), v.end());

   23         std::cout << "Sort: " << t.elapsed() << std::endl;

   24     }



#. Join 해봤습니다.

   25     {

   26         boost::timer t;

   27         std::string result = boost::algorithm::join(v, ",");

   28         std::cout << "Join: " << t.elapsed() << std::endl;

   29     }




-[ VS 2008 ]--------------
Sort: 0.178
Join: 0.104

-[ VS 2010 ]--------------
Sort: 0.079
Join: 0.029


 C++0x 이전에는 위 처럼 코딩 하지 말라고 했겠죠..
 사실 부자연 스러울 것이 없는 코드인데..
 하지 말라고 하는게 안타까운 상황이었습니다..ㅋ




Posted by U∙Seung

제가 구독하는 블로그 중에
rein님의 C++0x를 써서 Closure 다시 만들기와 C++기반의 closure를 보고
제가 쓰고 있던 방법도 공개 합니다.


사용할 수 있는 곳은 여러 곳이 있겠습니다만..
다른 곳으로 Message를 Passing 한다던가 Timer를 쓴다던가 할 때
유용하게 쓸 수 있겠습니다.




typedef
function<void (void)> Closure;


C++0x가 지원되면 std.function을 써도 되고
그렇지 않으면 boost.function을 쓰면 됩니다.




void
freef(int a, int b)

{

    cout << a << " + " << b << " = " << a+b << endl;

}

 

struct Class

{

    Class(int a): a_(a) {}

 

    void memf(int b)

    {

        cout << a_ << " - " << b << " = " << a_-b << endl;

    }

 

    int a_;

};

 

vector<Closure> closures;

{

    int a = 10;

    closures.push_back(bind(freef, a, 4));

    closures.push_back(bind(&Class::memf, new Class(a), 2));

//  closures.push_back([=](){ cout << a << endl; });

}

 

foreach(Closure& closure, closures)

{

    closure();

}



마찬가지로 std.bind 나 boost.bind를 사용하고,
C++0x가 지원되면 lambda를 추가적으로 사용할 수 있습니다.




Posted by U∙Seung