1 분 소요

개요

  • 복사 가능한 객체를 타입에 상관없이 담을 수 있는 클래스
  • typesafe void*라고 표현하기도 함
  • 값을 변경하는 경우 기존 객체의 소멸을 보장
  • any_cast 함수로 접근
    • 복사한 값을 반환하고 기존 객체 소멸
    • 타입이 다를 경우 bad_any_cast 예외 발생
    • any 객체가 포인터라면 접근이 가능한 경우엔 해당 포인터, 불가능하면 nullptr 반환
  • void*, reinterpret_cast는 typesafe 하지도 수명관리도 하지 않음
  • shared_ptr은 수명관리는 하지만 typesafe하지 않음
  • 저장할 타입을 알 수 있다면 optional, 타입들을 컴파일 시점에 알 수 있다면 variant를 사용하는 것이 좋음
    • any는 유연함을 위해 상대적으로 성능 하락이 존재


예제

  • 코드
    #include <any>
    #include <iostream>
    #include <string>

    using namespace std;

    class Test {
    	public:
    		Test() { cout << "Test()" << endl; }
    		Test(Test &&t) { cout << "Test(Test &&t)" << endl; }
    		Test(const Test &t) { cout << "Test(const Test &t)" << endl; }
    		~Test() { cout << "~Test()" << endl; }

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

    int main() {
    	any a = make_any<Test>();

    	cout << a.has_value() << endl;
    	cout << a.type().name() << endl;

    	cout << "------ 1" << endl;
    	any_cast<Test>(a).func();
    	cout << "------ 2" << endl;

    	cout << "------ 3" << endl;
    	any_cast<Test &>(a).func();
    	cout << "------ 4" << endl;

    	cout << "------ 5" << endl;
    	a = 1;
    	cout << "------ 6" << endl;

    	cout << a.type().name() << endl;
    	cout << any_cast<int>(a) << endl;

    	try {
    		cout << any_cast<string>(a) << endl;
    	} catch (bad_any_cast &e) {
    		cout << e.what() << endl;
    	}

    	cout << "------ 7" << endl;

    	cout << any_cast<int>(&a) << endl;
    	cout << *any_cast<int>(&a) << endl;
    	cout << any_cast<string>(&a) << endl;

    	cout << "------ 8" << endl;

    	a.reset();

    	return 0;
    }
  • 실행 결과
    Test()
    1
    4Test
    ------ 1
    Test(const Test &t)
    func()
    ~Test()
    ------ 2
    ------ 3
    func()
    ------ 4
    ------ 5
    ~Test()
    ------ 6
    i
    1
    bad any_cast
    ------ 7
    0x7fff76a0fb28
    1
    0
    ------ 8