Microsoft MVP성태의 닷넷 이야기
VC++: 97. C++ 템플릿 remove_pointer, enable_if, is_pointer 사용 예제 [링크 복사], [링크+제목 복사],
조회: 21366
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일

C++ 템플릿 remove_pointer, enable_if, is_pointer 사용 예제

처음 해결하고 싶었던 문제는 다음과 같은 식의 코드였습니다.

#include "stdafx.h"

using namespace std;
#include <map>

struct MyType { MyType() { } };

template <typename _Key, typename _Value>
class MapTS
{
public:
    MapTS()
    {
    }

    void SetNew(_Key key)
    {
        _Value v = new _Value();
        m_map.insert(pair<_Key, _Value>(key, v));
    }

private:
    map<_Key, _Value> m_map;
};

int main()
{
    MapTS<int, MyType *> m2;
    m2.SetNew(6);

    return 0;
}

위의 코드를 컴파일하면 다음과 같은 오류가 발생합니다.

Error C2440 'initializing': cannot convert from 'MyType **' to 'MyType *'

당연합니다. "_Value v = new _Value();" 코드가 다음과 같이 바뀌기 때문입니다.

MyType *v = new MyType *();

이를 해결하기 위해서는 포인터를 하나 제거한 타입을 구해야 하는데요. 이때 사용할 수 있는 것이 바로 remove_pointer 구문입니다. 따라서, 다음과 같이 해주면 해결할 수 있습니다.

template <typename _Key, typename _Value>
class MapTS
{
    typedef typename remove_pointer<_Value>::type _StructValue;

public:
    MapTS()
    {
    }

    void SetNew(_Key key)
    {
        _StructValue *v = new _StructValue();
        m_map.insert(pair<_Key, _Value>(key, v));
    }

private:
    map<_Key, _Value> m_map;
};

그런데, 동일한 코드로 포인터 없는 형태로도 사용하고 싶어졌습니다.

MapTS<int, MyType> m1;
m1.SetNew(5);

이렇게 사용하면 다음과 같은 오류가 발생하게 됩니다.

Error C2440 '<function-style-cast>': cannot convert from 'initializer list' to 'std::pair<_Key,_Value>'

역시 당연합니다. "MyType"을 주었기 때문에 m_map 변수의 타입이 "map<int, MyType>"으로 바뀌었고 SetNew 함수에서 포인터를 밀어넣으려니 오류가 발생하는 것입니다. 따라서, 포인터 없는 구문이 동작하려면 SetNew 함수가 다음과 같이 바뀌어야 합니다.

void SetNew(_Key key)
{
    _Value v = _Value();
    m_map.insert(pair<_Key, _Value>(key, v));
}

이를 해결하고 싶다면, 포인터 있는 경우와 없는 경우를 구분하고 그에 따른 템플릿 특수화를 해야 합니다. 이를 위해 is_pointer와 enable_if를 다음과 같이 적용해 줄 수 있습니다. (enable_if의 존재를 회사 동료가 알려줬는데... 전혀 예상치 못한 확장이었습니다. ^^;)

template <typename _Key, typename _Value>
class MapTS
{
    typedef typename remove_pointer<_Value>::type _StructValue;

public:
    MapTS() { }

    template<typename T = _Value>
    void SetNew(_Key key, typename enable_if< is_pointer<T>::value, T >::type value = nullptr)
    {
        _StructValue *v = new _StructValue();
        m_map.insert(pair<_Key, _Value>(key, v));
    }

    template<typename T = _Value>
    void SetNew(_Key key, typename enable_if< !is_pointer<T>::value, T >::type value = _Value())
    {
        m_map.insert(pair<_Key, _Value>(key, _Value()));
    }

private:
    map<_Key, _Value> m_map;
};

int main()
{
    MapTS<int, MyType> m1;
    m1.SetNew(5);

    MapTS<int, MyType *> m2;
    m2.SetNew(6);

    return 0;
}

(첨부 파일은 이 글의 예제 코드를 포함합니다.)




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]







[최초 등록일: ]
[최종 수정일: 5/31/2016]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 166  167  168  169  170  [171]  172  173  174  175  176  177  178  179  180  ...
NoWriterDateCnt.TitleFile(s)
733정성태5/29/200931696.NET Framework: 139. WPF - "M/d/yyyy h:mm:ss tt" 형식으로만 날짜를 출력하는 문제
732정성태5/27/200926745Team Foundation Server: 32. 팀 빌드 오류 확인 방법
731정성태5/27/200921759Team Foundation Server: 31. 팀 빌드 스케줄 확인 방법
730정성태5/26/200927295VS.NET IDE: 63. Visual Studio 2010 - Parallel Stacks [1]
729정성태5/25/200926955.NET Framework: 138. InternalsVisibleTo와 Public Key 값
728정성태5/23/200937449.NET Framework: 137. C#에서 Union 구조체 다루기파일 다운로드1
727정성태5/22/200922409오류 유형: 82. 메서드가 많은 경우 프록시 클래스 생성 실패
726정성태5/21/200921960VS.NET IDE: 62. Visual Studio 2010 Beta1 버그 피드백 - EnC기능 오류 [1]
725정성태5/21/200925234VS.NET IDE: 61. Visual Studio 2010 베타1과 Visual Studio 2008의 혼합 개발 [2]
724정성태5/19/200939366.NET Framework: 136. 자바와 닷넷의 압축 호환파일 다운로드2
723정성태5/18/200933308.NET Framework: 135. C# - Deflate, GZip, Zip
722정성태5/18/200921848개발 환경 구성: 45. SQL 서버 2008 백업 구성 [2]
721정성태5/14/200927512오류 유형: 81. Package 실행 오류 - Error 15404
720정성태5/13/200924272오류 유형: 80. SQL Server 2008 - Package 실행 오류의 구체적인 원인 확인
719정성태5/12/200925399.NET Framework: 134. WPF - XBAP을 호스팅하고 있는 인터넷 익스플로러 인터페이스 구하기파일 다운로드1
717정성태5/11/200925724개발 환경 구성: 44. VHD 파일 크기 확장하는 방법 - 두 번째 이야기
714정성태5/7/200924235Windows: 45. Windows 7 RC와 함께 공개된 Windows Virtual PC 베타
713정성태4/30/200956014오류 유형: 79. DLL 'xxxxx.dll'을(를) 로드할 수 없습니다. [1]
712정성태4/28/200928631오류 유형: 78. Windows Vista/2008에서의 MSXML4.cab 파일 배포 문제
711정성태4/27/200928245개발 환경 구성: 43. Hyper-V VHD 파일 크기 확장하는 방법
710정성태4/26/200928801.NET Framework: 133. CallbackOnCollectedDelegate was detected [4]파일 다운로드1
709정성태4/24/200925026개발 환경 구성: 42. Windows Vista SP1에서 사용 가능한 Hyper-V 관리 도구
708정성태4/23/200929939.NET Framework: 132. ClickOnce 배포를 명령행 수작업 구성파일 다운로드1
707정성태4/22/200929519개발 환경 구성: 41. Hyper-V에 Linux 설치 - SUSE Linux Enterprise Server 11
706정성태4/21/200925392.NET Framework: 131. ClickOnce - 그룹화시켜 다운로드파일 다운로드1
705정성태4/20/200920960개발 환경 구성: 40. TFS2008 SP1의 DBTier에 SQL Server 2008 SP1 설치 [1]
... 166  167  168  169  170  [171]  172  173  174  175  176  177  178  179  180  ...