[C++] 템플릿 정의에서 의미를 이해 할 수 없는 구문이 있습니다.

lavoid의 이미지

비주얼 스튜디오 2013의 visual c++에 추가되어있는 c++11 호환 가능한 utility 파일의 구문을 분석하던 중에 조금 의미를 이해할 수 없는 템플릿 정의 문장이 있어서 문의 드리고자 합니다.

구글에서 별짓을 다해 검색을 해봤지만 해당 사항에 대해서는 찾기가 힘들어 이 곳 고수분들의 조언을 듣고자 합니다.

아래 코드는 utility의 템플릿이 적용된 Pair 클래스의 오버로딩된 생성자 중 하나입니다.

 template<class _Other1,
        class _Other2,
        class = typename enable_if<is_convertible<_Other1, _Ty1>::value
            && is_convertible<_Other2, _Ty2>::value,
            void>::type>
        pair(_Other1&& _Val1, _Other2&& _Val2)
            _NOEXCEPT_OP((is_nothrow_constructible<_Ty1, _Other1&&>::value
                && is_nothrow_constructible<_Ty2, _Other2&&>::value))
        : first(_STD forward<_Other1>(_Val1)),
                second(_STD forward<_Other2>(_Val2))
        {   // construct from moved values
        }

위의 코드에서 템플릿 정의 부분을 봐주시기 바랍니다. 첫 번째, 두 번째 정의는 이름있는 템플릿 파라메터로 여기까지는 일반적인 템플릿 정의라고 이해하고 있습니다만, 문제는 세 번째의 이름없는 템플릿 파라메터 입니다. 이름없는 템플릿 파라메터의 부분을 제외한 오른쪽 부분은 대강 이해가 됩니다. 아마, is_convertible의 구조체에 2개의 템플릿 인자를 입력받아 두 번째 템플릿 인자로 변환이 될 수 있으면 true를 반환하겠죠(정확히는 integral_constance의 true_type 이겠습니다만..) 역시, 변환 될 수 없으면 false를 반환하는 것으로 생각합니다. 이것의 결과를 enable_if가 받아 특수화된 클래스중 하나를 선택하겠죠. (enable_if 의 두번째 템플릿 인자가 void로 되어있는것으로 보아 enable_if 결과가 중요하지 않은 것 처럼 보입니다만..)

이런식으로 작성된 궁극적인 이유는 새로생긴 좌측값 참조에 대해서 입력된 인자가 좌측값 참조로 넘겨질 것인지 아니면 참조로 넘겨질 것인지 가려내서 특수화된 생성자 중에서 알맞은 생성자를 선택하도록 하는 것이 목적이라고 생각합니다. 왜나하면 저런식으로 작성된 생성자가 참조 특수화 버전과, 좌측값 참조 특수화 버전이 있기 때문이죠.

이름없는 템플릿 파라메터인

class = typename enable_if<is_convertible<_Other1, _Ty1>::value
            && is_convertible<_Other2, _Ty2>::value,
            void>::type

이것이 컴파일 시간에서 어떤 작용을 하는 지와 어떻게 여기에서 참조 버전과 좌측값 참조 버전을 선택 할 수 있었는지 아시는 분들이 있으면 부디 답변을 부탁드리겠습니다!

kukyakya의 이미지

SFINAE(http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error)에 대해 찾아보세요.

C++에서 꽤 많이 사용되는 테크닉입니다.

class UnUsedType = enable_if<...>에서 어차피 사용하지 않을 UnUsedType을 생략한 형태가 class = enable_if<...>::type입니다.

lavoid의 이미지

위키의 SFINAE(치환 실패는 오류가 아니다)를 잘 읽어보았습니다.

그러니까.. enable_if<is_convertible<...>...>::type를 사용해서 형식을 비교하는 것이 아니고,
enable_if<is_convertible<...>...>::type를 사용함으로써 SFINAE를 유도하는 것이 주된 목적이라고 생각하는 맞는것 이겠지요?

이렇게 정의되어진 클래스는 템플릿 인자에서 먼저 형식을 추론하게 함으로써 위에 써져있던 좌측값 참조 생성자와 참조 생성자를
추론 후보로 올린다음 하나씩 대조하면서 일치하는 오버로드를 찾는 것. 이라고 이해 했습니다만,

뭔가 틀리게 이해한 점이 있다면, 지적해주시면 감사하겠습니다.

kaeri17의 이미지

&&는 우측값 참조입니다. 저도 좀 헷갈렸는데, 하여간 저게 우측값 참조와 그냥 참조를 구분하는 역할을 하지는 않는 것 같은데요? _Ty1, _Ty2 는 pair의 멤버들의 타입인듯 보이는데요? 그럼 그냥 저 구문은 pair생산자의 인자가 맞는지 컴파일타임에 역할만 하는것 같은데요? 그리고 어떤 값이 우측값 참조인지는 저런 구문 없이도 자동으로 선택이 되는것으로 아는데요...

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.