«   2024/03   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
Archives
Today
Total
03-30 00:03
관리 메뉴

lancelot.com

Empty class and Tag dispatching 본문

프로그래밍

Empty class and Tag dispatching

lancelot50 2022. 7. 15. 00:28
  • Tag dispatching
    • empty class 를 이용해서 함수 오버로딩을 설명적인 코드로 만드는 테크닉
    • tag dispatching 에 사용되는 empty class 를 tag_type이라고도 함
  • Tag dispatching 예시 1
#include<iostream>
#include<mutex>

struct adopt_lock_t
{
	explicit adopt_lock_t() = default;
};

constexpr adopt_lock_t adopt_lock;


template<class Mutex>
class lock_guard
{
public :
	using mutex_type = Mutex;
	explicit lock_guard(Mutex& mtx) : mtx(mtx)	{ mtx.lock();}
	explicit lock_guard(Mutex& mtx, adopt_lock_t) : mtx(mtx) { }

	~lock_guard() noexcept { mtx.unlock(); }

	lock_guard(const lock_guard&) = delete;
	lock_guard& operator=(const lock_guard&) = delete;

private:
	Mutex& mtx;
};

std::mutex m1,m2;

int main()
{
	lock_guard g1(m1);

	m2.lock();
	lock_guard g2(m2, adopt_lock);
//	lock_guard g2(m2, {} ); adopt_lock_t = {}  를 error 로 만들기 위해 생성자가 명시적으로 있어야하도록 함
}

 

  • Tag dispatching 예시 2
#include<iostream>
#include<mutex>

std::mutex m;

int main()
{
	std::unique_lock u1(m, std::adopt_lock);
	std::unique_lock u2(m, std::defer_lock);
	std::unique_lock u3(m, std::try_to_lock);

	int* p1 = new int[10]; // 실패시 std::bad_alloc 예외 발생
	delete[] p1;

	int* p2 = new(std::nothrow) int[10]; // 실패시 0 반환
	delete[] p2;
}

 

// Mutex lock 을 위한 empty class ( C++11 )
struct adopt_lock_t { explicit adopt_lock_t() = default; };
struct defer_lock_t { explicit defer_lock_t() = default; };
struct try_to_lock_t { explicit try_to_lock_t() = default; };

constexpr adopt_lock_t adpt_lock{};
constexpr defer_lock_t defer_lock{};
constexpr try_to_lock_t try_to_lock{};
// nothrow new (C++98)
struct nothrow_t { explicit nothrow_t()=default; };
nothrow_t const nothrow;

void* operator new(std::size_t sz)
{
	// 실패시 throw std::bad_alloc
}

void* operator new(std::size_t sz, std::nothrow_t) noexcept
{
	// 실패시 0 반환
}