C++ variant 기초 사용 & 상속 캐스팅과 비교

#include <iostream>
#include <variant>
#include <vector>
#include <chrono>

using namespace std;

struct Object
{
};

struct Object0 : public Object
{
	int value;
};

struct Object1 : public Object
{
	vector<int> values;
};

struct Object2 : public Object
{
	string values;
};

struct Object3 : public Object
{
	wstring values;
};

int main()
{
	variant<Object0, Object1, Object2, Object3> var;

	cout << "size" << endl;
	cout << "Object0 : " << sizeof(Object0) << endl;
	cout << "Object1 : " << sizeof(Object1) << endl;
	cout << "Object2 : " << sizeof(Object2) << endl;
	cout << "Object2 : " << sizeof(Object3) << endl;
	cout << "variant : " << sizeof(var) << endl;

	var = Object0(); // 이 코드가 없으면 아래 값을 설정할때 에러가 발생함. variant의 타입이 정해지지 않기 때문인듯.
	get<Object0>(var).value = 0;
	cout << "variant Object0 value: " << get<Object0>(var).value << endl;

	constexpr int COUNT = 100'000'000;

	{
		auto caseStr = "case variant"s;
		auto startTime = chrono::steady_clock::now();

		volatile int64_t accValue = 0;
		for (int i = 0; i < COUNT; i++)
		{
			Object0& rObj = get<Object0>(var);
			rObj.value = i;
			accValue += rObj.value;
		}

		auto endTime = std::chrono::steady_clock::now();

		cout << format("{}({}) : {}ms, accValue={}", 
			caseStr, 
			COUNT, 
			chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count(), 
			(int) accValue) << endl;
	}

	{
		Object* pObj = new Object0();

		auto caseStr = "case pointer"s;
		auto startTime = chrono::steady_clock::now();

		volatile int64_t accValue = 0;
		for (int i = 0; i < COUNT; i++)
		{
			Object0& rObj = *(static_cast<Object0*>(pObj));
			rObj.value = i;
			accValue += rObj.value;
		}

		auto endTime = std::chrono::steady_clock::now();

		cout << format("{}({}) : {}ms, accValue={}",
			caseStr,
			COUNT,
			chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count(),
			(int)accValue) << endl;
	}

	return 0;
}
size
Object0 : 4
Object1 : 24
Object2 : 32
Object2 : 32
variant : 40
variant Object0 value: 0
case variant(100000000) : 47ms, accValue=887459712
case pointer(100000000) : 44ms, accValue=887459712

variant가 사알짝 느림.
하지만 한번 설정한 타입에 대해서 이후 다른 타입으로 접근시 익셉션을 발생시켜 준다는 점에서 안정성은 좋을듯.

타입세이프 유니온이라는 이름에 걸맞는듯.

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다