ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [1] - Templates - 1
    C++ 2021. 8. 5. 23:04

    Ref

    1. (https://www.geeksforgeeks.org/generics-in-c/)

    : Generics in C++

    코드의 재사용성 향상, Function overloading의 최소화. 데이터 타입에 따라 같은 코드를 반복할 필요가 없습니다.

    コードの再利用性向上、Function Overloadingの最小化。データタイプによる重複コード最小化。

    2. (https://www.geeksforgeeks.org/templates-cpp/)

    3. (https://levelup.gitconnected.com/advanced-c-templates-tutorial-7b54259b2671)

    4. (https://www.geeksforgeeks.org/templates-and-static-variables-in-c/)

    5. (https://www.geeksforgeeks.org/template-specialization-c/)

    6. (https://en.cppreference.com/w/cpp/language/template_specialization)

    7. (https://www.geeksforgeeks.org/template-metaprogramming-in-c/)

    8. (https://en.wikipedia.org/wiki/Template_metaprogramming)

    9. (https://en.wikipedia.org/wiki/Metaprogramming)

    10. (https://en.cppreference.com/w/cpp/language/variable_template)-> Variable Template (Hard)

    11. (https://en.wikipedia.org/wiki/Turing_completeness) ->About Turing Completeness.

    12. (http://www.cplusplus.com/forum/beginner/220104/)-> About Concrete data type. ADT vs CDT?

    13. (https://en.cppreference.com/w/cpp/language/sfinae)-> barely possible to understand

    : Function Templates, Class Templates, any other templates.

    매크로 처럼 Compile time에 Expand합니다. Source code는 하나의 함수를 갖지만 Compile이 완료된 code는 데이터 타입이 다른 몇 가지의 같은 함수를 갖고 있을 수 있습니다.

    Function overloading은 OOP의 Polymorphism의 특징 중 하나입니다. Function overloading과 templates의 두드러지는 차이점은 Function overloading은 두 개 이상의 함수가 기본적으로 비슷한 동작을 제공하는 것이 주된 목적이지만 template는 서로 다른 data type에 대해 완전히 같은 operation을 제공하는 것이 주된 목적입니다.

     만약, function template가 static variable을 포함하고 있을 경우 다른 data type마다 서로 다른 인스턴스가 생성됩니다.

    class template의 경우도 사정은 비슷합니다. 서로 다른 data type의 instance는 다른 static member를 갖게 됩니다.

    2와 1을 결과로 얻게 될 것입니다.

    같은 함수라도 데이터 타입에 따라서 다르게 행동하는 함수를 작성할 수 있을까? C++에서는 어떤 데이터 타입에 대해서만 특별한 행동을 정의하는 것이 가능합니다. Template Specialisation.

    char에 대해서만 다른 결과 값을 얻게 될 것입니다. Template Specialisation! 이는 Class에 대해서도 비슷하게 적용할 수 있습니다.

    compiler는 마주치는 데이터 마다 templates의 복사본을 생성합니다. 특히, Specialised template가 존재하면 가장 먼저 해당 데이터 타입이 Specialised된 데이터 타입인지 확인합니다. 허나, 이 specialisation은 Class와 Function에 한정되는 것이 아닙니다. Variable template에 대해서도 Specialisation이 가능합니다.

    Template Metaprogramming

    이 표현의 결과는 1024입니다. 재귀적으로 호출이 된다는 직관은 갖을 수 있으나 여기서 핵심적인 내용은 해당 결과값은 Runtime이 아니고 Compile time에 결정이 된다는 사실입니다. 이걸 계산한 건 Compiler입니다.

    ( MetaProgramming -> 어떤 컴퓨터 프로그램이 다른 컴퓨터 프로그램을 마치 하나의 데이터처럼 취급할 수 있는 프로그래밍 기법을 의미합니다. 다른 프로그램을 Data type으로 다룰 수 있는 능력 뿐만이 아니라 다른 프로그램을 읽고, 만들고 자기 자신의 프로그램을 수정할 수도 있는 능력을 포함합니다. 또한 Runtime에 처리해야할 계산을 Compile Time에 처리한다는 특징도 갖고 있습니다. 그리고 어떤 프로그래밍 언어가 자기 자신의 metaprogramming language가 될 수 있는 능력을 Reflection이라고 합니다. )

    template의 parameter와 enum type에는 다음과 같은 특징이 있습니다.

    1. template의 parameter는 Nontype이어도 상관이 없다.

    2. enum type은 Compile time에 결정된다.

    3. Compiler는 Template에 대한 새로운 Arguments를 발견하면 새로운 instance를 만든다.

    StructFoo<8>::val은 parameter인 8을 바탕으로 인스턴스를 만드려 시도할 것입니다. 그런데 StructFoo<8>을 만드려면 StructFoo<7>의 인스턴스가 필요하고 StructFoo<6>이..., ..., 이런 식으로 StructFoo<0>까지 오게 될 것입니다. 그런데StructFoo<0>는 Specialised template로 아래에 따로 정의가 되어 있습니다. 이렇게 Compile time에 Computation을 실시 할 수 있고 이를 가리켜 "Template Metaprogramming"이라고 합니다. 추가적으로 알아두면 잘난 체 할 수 있는 사실이 하나 있는데 Template metaprogramming은 Turing Complete하다는 것입니다.

    SFINAE[Substitution Failure is Not an Error]

    Compiler가 template를 컴파일 할 땐, 크게 두 페이즈[phase]에 걸쳐 진행됩니다. 첫 페이즈에서는 template code를 분리하고 두 번째 페이즈에서 Syntax error를 검사하고 template parameter에 종속되지 않는 변수, 함수 등을 검사합니다. 또, 두 번째 페이즈에서는 주어진 CDT[Concrete Data Type]를 바탕으로 template를 instantiate하며 다시 한 번 CDT과 template가 Valid한지 검증합니다.

    SFINAE는 Specialised Template Function과 관련이 있습니다. 우리는 이전에 template의 특정한 데이터 타입에 한해서 다른 함수를 동작할 수 있도록 했습니다. 그런데 함수의 경우엔 이렇게 구성을 할 수가 없기 때문에 SFINAE Principle를 이용하는 것입니다. 이 과정은 컴파일러가 template을 Compile하는 두 번째 페이즈와 관련이 있습니다.

    이 코드를 바탕으로 SFINAE를 설명합니다.

    이 코드는 어떤 오브젝트가 오든 같은 operation을 제공하며 template의 개념이 그렇게 의도되어 있습니다. 그런데 MyClass Object에 대해서만 다른 행동을 하도록 만들고 싶다면 어떻게 하면 좋을까요?

    const로 만들어 주지 않으면 컴파일 에러가 납니다. Constant instance에서 non-constant member function을 호출하는 것은 불법입니다.

    다음과 같이 Print를 하나 더 만드는 방법은 당연히 통하지 않습니다. 같은 이름에 다른 함수가 정의되어 있다며 컴파일러가 에러를 냅니다.

    단순히 함수를 하나 더 정의하면 다음과 같은 오류를 얻습니다.

    여기서 활약하는 것이 SFINAE Principle입니다. 가장 단순하게 위의 문제를 해결할 수 있는 방법은 다음과 같이 함수를 작성하는 것입니다.

    이 문장 자체가 Print함수의 반환값입니다.

    가장 먼저 typename이라는 키워드는 뒤에 오는 enable~~이것이 variable이 아니라 어떤 type이라는 것을 컴파일러에게 알리는 것입니다.

    enable_if의 parameter is_same은 안의 T와 MyClass가 같다면 true를 반환하여 value의 값이 결정됩니다. 그리고 enable_if 자체는 value가 true라면 std::enable_if::type이라는 type으로 결정되지만 false라면 정의되지 않습니다. 이것이 정의되지 않으면 invalid하다는 뜻이고 SFINAE principle에 따라서 template instantiate가 무시됩니다. 그래서 second phase와 관련이 있다고 했던 것입니다.

    다른 해결방법도 존재합니다. 그런데 하다보니 내용이 방대하고 Critical한 것 같아서 따로 하는 편이 나을 것 같습니다.

     

     

    'C++' 카테고리의 다른 글

    [ Anything ] - Iterator - 2  (0) 2021.09.08
    [ Anything ] - Iterator - 1  (0) 2021.09.07
    [ Anything ] - Permutation and Combination  (0) 2021.08.29
    [2] - Templates - 2  (0) 2021.08.08
    [ Anything ] - Object Slicing  (0) 2021.05.20
Designed by Tistory.