types_add_pointer

types_add_pointer (포인터 추가)

std::add_pointer는 주어진 타입에 포인터를 추가하는 C++ 타입 특성(type trait)이에요. 참조 타입을 처리할 때는 참조 대상 타입을 가리키는 포인터를 만들고, cv 또는 ref 한정 함수 타입은 그대로 유지해요. 이 도구는 템플릿 메타프로그래밍에서 타입 변환을 깔끔하게 표현할 때 유용해요.

출처: cppreference

본문

<type_traits> 헤더에 정의되어 있어요. C++11부터 사용할 수 있어요.

  • T가 참조 타입이라면, 멤버 typedef type은 참조되는 타입을 가리키는 포인터가 돼요.
  • 그렇지 않고 T가 객체 타입, cv 또는 ref 한정이 없는 함수 타입, 또는 (cv 한정일 수 있는) void 타입이라면, 멤버 typedef typeT* 타입이 돼요.
  • 그 외의 경우(T가 cv 또는 ref 한정 함수 타입이라면), 멤버 typedef typeT 타입 그대로예요.
  • 프로그램이 std::add_pointer에 특수화를 추가하면 동작이 정의되지 않아요.

멤버 타입 (Member types)

이름 설명
type T 또는 T가 참조하는 타입을 가리키는 포인터

헬퍼 타입 (Helper types)

C++14부터 다음 별칭 템플릿을 사용할 수 있어요.

template < class T > using add_pointer_t = typename add_pointer < T >:: type ;

가능한 구현 (Possible implementation)

namespace detail { template < class T > struct type_identity { using type = T ; }; // or use std::type_identity (since C++20) template < class T > auto try_add_pointer ( int ) -> type_identity < typename std :: remove_reference < T >:: type *> ; // usual case template < class T > auto try_add_pointer (...) -> type_identity < T > ; // unusual case (cannot form std::remove_reference<T>::type*) } // namespace detail template < class T > struct add_pointer : decltype ( detail :: try_add_pointer < T > ( 0 )) {};

예제 (Example)

#include <iostream>
#include <type_traits>

template<typename F, typename Class>
void ptr_to_member_func_cvref_test(F Class::*)
{
    // F is an "abominable function type"
    using FF = std::add_pointer_t<F>;
    static_assert(std::is_same_v<F, FF>, "FF should be precisely F");
}

struct S
{
    void f_ref() & {}
    void f_const() const {}
};

int main()
{
    int i = 123;
    int& ri = i;
    typedef std::add_pointer<decltype(i)>::type IntPtr;
    typedef std::add_pointer<decltype(ri)>::type IntPtr2;
    IntPtr pi = &i;
    std::cout << "i = " << i << '\n';
    std::cout << "*pi = " << *pi << '\n';

    static_assert(std::is_pointer_v<IntPtr>, "IntPtr should be a pointer");
    static_assert(std::is_same_v<IntPtr, int*>, "IntPtr should be a pointer to int");
    static_assert(std::is_same_v<IntPtr2, IntPtr>, "IntPtr2 should be equal to IntPtr");

    typedef std::remove_pointer<IntPtr>::type IntAgain;
    IntAgain j = i;
    std::cout << "j = " << j << '\n';

    static_assert(!std::is_pointer_v<IntAgain>, "IntAgain should not be a pointer");
    static_assert(std::is_same_v<IntAgain, int>, "IntAgain should be equal to int");

    ptr_to_member_func_cvref_test(&S::f_ref);
    ptr_to_member_func_cvref_test(&S::f_const);
}

출력:

i = 123
*pi = 123
j = 123

결함 보고 (Defect reports)

다음 동작 변경 결함 보고는 이전에 발표된 C++ 표준에 소급 적용되었어요.

DR 적용 대상 게시된 동작 올바른 동작
LWG 2101 C++11 std::add_pointer는 cv/ref 한정 함수 타입에 대한 포인터를 생성해야 했어요. cv/ref 한정 함수 타입 자체를 생성해요.

같이 보기 (See also)

is_pointer (C++11) 타입이 포인터 타입인지 확인해요 (클래스 템플릿)
remove_pointer (C++11) 주어진 타입에서 포인터를 제거해요 (클래스 템플릿)
add_pointer (C++26) 반영된 타입에 포인터를 추가해요 (함수)

더 알아보기 (Learn more)

cppreference