Library2010. 11. 9. 12:18

reference_wrapper 는 클래스, 함수, 변수 등의 참조를 레핑 한다.
참조(포인트)값을 사용할때 명시적으로 지정할수 있다.
클래스에서는 추상화 등에서도 유용하게 사용할수 있을듯 하다.


#include "FUNCTIONAL"
using std::tr1::reference_wrapper;
using std::tr1::cref;

#include "IOSTREAM"
using std::cout;
using std::endl;

class base
{
public:
	virtual void ShowMe()
	{
		cout << "base" << endl;
	}
};

class derived_first	: public base
{
public:
	void ShowMe()
	{
		cout << "derived_first" << endl;
	}
};

class derived_second : public base
{
public:
	void ShowMe()
	{
		cout << "derived_second" << endl;
	}
};

void ShowMe1()
{
	cout << "ShowMe1 func" << endl;
}

void ShowMe2()
{
	cout << "ShowMe2 func" << endl;
}

void main(void)
{
	derived_first	first;
	derived_second	second;
	
	reference_wrapper wr_first(first);	
	reference_wrapper wr_second(second);	

	wr_first.get().ShowMe();
	wr_second.get().ShowMe();

	typedef void(*const FUNC)();	
	reference_wrapper wr_func(&ShowMe1);	//전역 함수의 레퍼런스

	wr_func();

	wr_func = cref(&ShowMe2);			//함수 변경
	wr_func();
}

Posted by 상현달
Library2010. 11. 8. 11:59

mem_fn 의 함수 템플릿은 함수 포인트를 호출할수 있도록 포장한다.
result_of 함수 템플릿을 사용하다면 보면 리턴값의 정의가 애매모호해 지는 경우 사용한다.


#include "stdio.h"

#include 

using std::tr1::mem_fn;
using std::tr1::result_of;

class func_class
{
public:
	void print() const
	{
		printf("Hello world!!!\n");
	}
	void print_arg(char* string)
	{
		printf("%s\n", string);
	}
	int printf_return()
	{
		return 1;
	}

public:
	int mem_;
};

template 
func_print(FN fn, OB ob)
{
	//result_of 은 코딩시 리턴 형식을 정의 할수 없는 애매한 상황에 사용된다.
	typedef typename result_of::type ret;

	ret ret_val = fn(ob);

	printf("Return type of %s when called with %s is %s(%d)\n",
		   typeid(FN).name(), 
		   typeid(OB).name(), 
		   typeid(ret).name(),
		   ret_val);
	
}

void main(void)
{
	typedef void(func_class::*FUN_PRINTF)() const;
	FUN_PRINTF fn = &func_class::print;

	func_class fc;
	// 인자 없는 함수
	mem_fn(fn)(fc);					

	//인자 있는 함수
	mem_fn(&func_class::print_arg)(fc, "Hello world!!!");

	//반환 있는 함수
	func_print(mem_fn(&func_class::printf_return), fc);

	//멤버 변수 사용
	mem_fn(&func_class::mem_)(fc) = 3;
	printf("%d\n", fc.mem_);

}

Posted by 상현달
Library2010. 1. 27. 12:44

TR1 에서 4개의 컨테이너가 추가되었다

- unordered_map
- unordered_multimap
- unordered_set
- unordered_multiset

기존의 STL 에서도 가지고 있던 컨테이너다. 무엇이 다른가 ?

장점
- 일반 정렬 컨테이너는 데이타가 추가될때 값을 정렬시켜서 보관해서 검색하지만, 이것들은 hash 알고리즘을 이용하여 검색한다.

단점
- STL 에 비해 적은 연산자를 지원한다. 아마도 성능에 최적화 하기 위해서 일까 ?(rbegin 등도 사용할수 없다.)

기존에 많이들 쓰던거라 딱히 예제를 보여줄것도 없다.

허전하니 이런거라도 ...


#include 
#include 


int _tmain(int argc, _TCHAR* argv[])
{     
    using namespace std::tr1;    

    unordered_map map;
    unordered_multimap multimap;
    unordered_set set;
    unordered_multiset multiset;    

    return 0;
}
Posted by 상현달
Library2010. 1. 19. 19:16

이번에는 Smart Pointer 이다. new 해서 사용해도 delete 할필요가 없다.
Java 나 C# 에서와 같이 자기참조 카운터를 관리하고 카비지 컬렉터도 가지고 있다. 물론 다중스레드에서도 안전하다.

#include <boost/tr1/tr1/memory> 해더가 필요하다.

기본 사용법

int _tmain(int argc, _TCHAR* argv[])
{       
    std::tr1::shared_ptr sp1(new int);
    *sp1 = 1; // 값 대입
    std::tr1::shared_ptr sp2(new int(5));
    std::cout << "sp1 의 값:"   << *sp1 << std::endl;
    std::cout << "sp1 의 주소:" << sp1 << std::endl;
    std::cout << "sp2 의 값:"   << *sp2 << std::endl;
    std::cout << "sp2 의 주소:" << sp2 << std::endl;
    std::cout << std::endl;

    *sp1 = *sp2; //call by value
    sp2.reset(new int(9));
    std::cout << "sp1 의 값:"   << *sp1 << std::endl;
    std::cout << "sp1 의 주소:" << sp1 << std::endl;
    std::cout << "sp2 의 값:"   << *sp2 << std::endl;
    std::cout << "sp2 의 주소:" << sp2 << std::endl;
    std::cout << std::endl;

    sp1 = sp2; //call by reference
    *sp1 = 7;
    std::cout << "sp1 의 값:"   << *sp1 << std::endl;
    std::cout << "sp1 의 주소:" << sp1 << std::endl;
    std::cout << "sp2 의 값:"   << *sp2 << std::endl;
    std::cout << "sp2 의 주소:" << sp2 << std::endl;

    return 0;
}

실행결과:

sp1 의 값:1
sp1 의 주소:00032F78
sp2 의 값:5
sp2 의 주소:00032FE8

sp1 의 값:5
sp1 의 주소:00032F78
sp2 의 값:9
sp2 의 주소:000313D8

sp1 의 값:7
sp1 의 주소:000313D8
sp2 의 값:7
sp2 의 주소:000313D8



메모리 해제를 사용자 정의 함수로 처리가 가능하다.
class deleter 
{ 
public:
    void operator()(int *p) 
    { 
        std::cout << "delete_operator" << std::endl;
        delete p; 
    } 
    static void Deleter(int* p)
    { 
        std::cout << "delete_static_method" << std::endl;
        delete p; 
    } 
};

void deleter_method(int *p)
{
    std::cout << "delete_method" << std::endl;
    delete p; 
}

int _tmain(int argc, _TCHAR* argv[])
{       
    std::tr1::shared_ptr sp1(new int(5), deleter());
    std::tr1::shared_ptr sp2(new int(5), deleter_method);
    std::tr1::shared_ptr sp3(new int(5), deleter::Deleter);

    return 0;
}



실행결과:

delete_static_method
delete_method
delete_operator




응용편~ 요런걸 사용해도 메모리 해제의 부담이 없다.
class Animal_Interface
{
public:
    virtual void Crying() = 0;
};

class Animal_dog : public Animal_Interface
{
public:
    void Crying() {std::cout << "멍멍멍 !!!" << std::endl;};
};

class Animal_cat : public Animal_Interface
{
public:
    void Crying() {std::cout << "야옹~" << std::endl;};
};

int _tmain(int argc, _TCHAR* argv[])
{   
    std::tr1::shared_ptr dog(new Animal_dog);
    std::tr1::shared_ptr cat(new Animal_cat);

    dog->Crying();
    cat->Crying();

    return 0;
}



실행결과:
멍멍멍 !!!
야옹~



주의 할점 !!! shared_ptr 을 사용할때 하나의 포인터를 두개의 shared_ptr 이 참조하면 두번 삭제(delete) 하므로 crash를 발생할 수 있다.
void Crash_Double_Ref_1()
{
    int* p = new int;

    std::tr1::shared_ptr sp1(p);
    std::tr1::shared_ptr sp2(p);    
}
//함수가 종료되면 스레드 스텍에서 sp1 이 p 를 제거(delete) 하고
//sp2 가 또 p 를 제거 하므로 sp2 가 제거할때 crash 발생한다.

void Crash_Double_Ref_2(int* p)
{
    std::tr1::shared_ptr sp1(p);
}
//함수가 종료되면 sp1 이 p 를 제거(delete)한다.

int _tmain(int argc, _TCHAR* argv[])
{   
    Crash_Double_Ref_1();

    int* p = new int;

    Crash_Double_Ref_2(p);

    delete p;    
    //Crash_Double_Ref_2 가 p 를 제거 했기 때문에 delete 할때 crash

    return 0;
}


하나의 포인터를 두개의 shared_ptr 로 사용한던지, 다른 포인터 변수에서 생성된 포인터를 사용하는 일은 습관적으로 하지 말것을 권장 !!!
Posted by 상현달
Library2010. 1. 14. 10:57


여러개의 객체를 하나로 묶어 쓸수 있다. 기존에 stl 에 pair 는 두개만 묶어서 사용했지만 tbple 은 최대 10개의 객체를 묶어서 사용할수 있다.

10 마디 말보다 1줄 코딩이 이해하기 빠르다~

#include 


using std::tr1::tuple;
using std::tr1::make_tuple;
using std::tr1::get;
using std::tr1::tie;

void Printtuple(tuple t)
{        
    std::cout << get<0>(t) << ", ";
    std::cout << get<1>(t) << ", ";
    std::cout << get<2>(t).c_str();
    std::cout << std::endl;
}

template
int GetTuplesize(const TupleSize&)
{
    return std::tr1::tuple_size::value;
}

int _tmain(int argc, _TCHAR* argv[])
{    
    //===== tuple 생성
    //일괄 생성
    tuple t = make_tuple(1, 'A', "TEST");
    Printtuple(t);
    
    //하나씩 생성
    tuple t1;
    //tuple 의 각각 원소에 접근하기 위해 get 메소드를 사용한다.
    //메소드 인자로 상수값(const)만 받을수 있어서 아쉽다.
    get<0>(t1) = 2;
    get<1>(t1) = 'B';
    get<2>(t1) = "TEST1";    
    Printtuple(t1);
    //===== tuple 생성
    
    
    //===== tuple 일괄 참조
    int n = 0;
    char c = 'C';
    std::string str = "NONE";

    //첫번째 요소만 읽고 두번째, 세번째 요소는 필요 없을 경우..
    tie(n, std::tr1::ignore, std::tr1::ignore) = t;
    std::cout << n << ", " << c << ", " << str.c_str() << std::endl;

    //모든 요소를 읽는다.
    tie(n, c, str) = t;
    std::cout << n << ", " << c << ", " << str.c_str() << std::endl;   
    //===== tuple 일괄 참조

    //===== tuple 요소 카운트
    std::cout << "size: " << GetTuplesize(t) << std::endl;
    //===== tuple 요소 카운트

    return 0;
}


실행결과:
1, A, TEST
1, B, TEST1
1, C, NONE
1, A, TEST
3

Posted by 상현달