개념

std::in_place_t는 C++17 표준 라이브러리에서 도입된 tag type이다. 생성자 호출 시 내부 객체를 직접 생성하겠다는 의도를 전달하기 위해 사용되는 특별한 타입이다.

std::optional, std::variant, std::any 같은 컨테이너 클래스에서 내부 값을 초기화할 생성자 인자를 전달하고자 할 때 사용된다.

이 타입의 목적은 **“이 생성자 호출은 내부 객체의 생성자 인자로 전달된다”**는 것을 컴파일러와 사람 모두에게 명확히 하기 위함이다.

tag type이란?

tag type특별한 의미를 전달하기 위해 만들어진 빈 struct나 class 타입을 의미한다.

값을 전달하기 위해서가 아니라 **의도를 전달하기 위한 타입 기반 신호(signal)**로 쓰인다. 주로 함수나 생성자 오버로딩에서 어떤 버전을 호출할지를 구분짓는 역할을 한다.

예시:

  struct my_tag_t {};
constexpr my_tag_t my_tag{};
  

이렇게 tag type을 만들고, 함수 호출 시 my_tag를 인자로 넘겨서 어떤 오버로드 버전을 호출할지를 구분할 수 있다.

std::in_place_t 정의

std::in_place_t는 표준 라이브러리에서 다음과 같이 정의되어 있다.

  namespace std {
    struct in_place_t { explicit in_place_t() = default; };
    inline constexpr in_place_t in_place{};
}
  

std::in_placestd::in_place_t 타입의 상수 객체로, 생성자나 함수에 인자로 넘겨 사용한다.

구현 예시는 다음 링크에서 확인 가능하다: https://en.cppreference.com/w/cpp/utility/in_place

활용 예시

std::optional에서 사용

  #include <optional>
#include <string>
#include <iostream>

int main() {
    std::optional<std::string> opt1("hello");  // 문자열 리터럴로 생성

    std::optional<std::string> opt2(std::in_place, 5, 'x');  // string(5, 'x') 생성자 호출

    std::cout << *opt1 << std::endl;  // 출력: hello
    std::cout << *opt2 << std::endl;  // 출력: xxxxx
}
  

첫 번째는 "hello"라는 문자열을 미리 만들어 optional에 저장하는 방식이고, 두 번째는 optional 내부의 std::string 객체를 string(5, ‘x’) 생성자로 직접 초기화하는 방식이다.

std::in_place가 없으면 std::optional<std::string> opt(5, 'x');와 같이 모호성 에러가 발생할 수 있다.

std::variant에서 사용

  #include <variant>
#include <string>
#include <iostream>

int main() {
    std::variant<int, std::string> v1(std::in_place_index<1>, 5, 'x');
    std::variant<int, std::string> v2(std::in_place_type<std::string>, 5, 'x');

    std::cout << std::get<1>(v1) << std::endl;  // 출력: xxxxx
    std::cout << std::get<1>(v2) << std::endl;  // 출력: xxxxx
}
  

std::in_place_index<1>은 인덱스 1(std::string) 타입을 선택하여 생성자를 호출한다. std::in_place_type<std::string>는 타입으로 직접 선택한다.

이 방식으로 어떤 타입의 값을 생성할지와 생성자 인자를 명시적으로 지정할 수 있다.

장점

  • 생성자 오버로딩에서 의도를 명확히 표현할 수 있다.
  • 컴파일 타임에 타입 안전성을 확보할 수 있다.
  • 모호성(ambiguity)을 방지할 수 있다.