프로그램/C,C++

[C++ 기본] 7. template function

naudhizb 2022. 1. 16. 00:02
반응형
// 7_함수템플릿1.cpp
#include <iostream>
//#include <stdio.h>

// cl /Tc 소스.cpp     : C 언어
// cl /Tp 소스.cpp     : C++ 언어

// 모든 타입에 동작하는 함수 만들기 - C언어
// 매크로 함수
//#define square(x) ((x)*(x))

// C++ : int 버전과 double 버전을 따로 만들자
//    방법 1. 사용자가 직접 만들자
//    방법 2. 함수 템플릿을 만들자. 컴파일러가 함수 생성

// Code Bloat : 템플릿 사용시 컴파일러가 너무 많은 함수(클래스)
//                를 만들어서 목적코드가 커지는 현상
template<typename T> 
T square(T a)
{
    // __FUNCTION__  : 함수 이름을 담은 C++ 표준 매크로.
    // __FUNCSIG__ : 함수이름+signature. C++ 표준 아님.
    //                  VC++ 만 지원
    // __PRETTY_FUNCTION__ : g++에서 지원

    std::cout << __FUNCSIG__ << std::endl;

    return a * a;
}

int main()
{
    square(3);
    square(3.4);

    short s = 3;
    square(s);


    int n = 3;
    int ret = square(++n); // ((++n)*(++n))

    printf("%d\n", ret);
    //std::cout << ret << std::endl; // ??    
}

잘 생각해보면 C언어에서도 template과 같은 기능을 수행한 적이 있을 것이다. 바로 define문을 이용한 macro function이다. 하지만, 매크로 함수 사용 시 가장 중요한 주의점이 바로 전처리기에 의한 효과가 어떻게 발현될지 모르는 문제였다. template function은 그러한 문제를 해결한다.

추가로 최신의 C표준, C++표준에서는 함수 이름을 매크로로 지원한다. 다만, 일부 기본정의 매크로의 경우 컴파일러마다 다르게 설정된다.

#include <iostream>

/*
int Add(int a, int b)
{
    return a + b;
}
*/
/*
template<typename T> 
T Add(T a, T b)
{
    return a + b;
}
*/
/*
template<typename T1, typename T2>
T1 Add(T1 a, T2 b)
{
    return a + b;
}
*/
// 반환타입 해결책1. 템플릿 인자로 타입을 전달 받는다.
template<typename R, typename T1, typename T2>
R Add(T1 a, T2 b)
{
    return a + b;
}

int main()
{
    //std::cout << Add<int, double>(1, 2.5 ) << std::endl;

    std::cout << Add<double>(1, 2.5) << std::endl;
}

template 을 이용하여 함수 인자 뿐만 아니라 함수 반환타입 또한 정의할 수 있다. 그리고 template을 이용한 함수는 default 타입이 정의되어 있으므로 일부를 생략하여 사용할 수 있다.

// reference: https://blog.naver.com/wjdeh313/222618643998
#include <iostream>

// decltype(a+b) : a+b를 했을때 나오는 타입
//                실제로 더하기를 하는 것은 아님.

template<typename T1, typename T2>
//decltype(a+b) Add(T1 a, T2 b)

//auto Add(T1 a, T2 b)->decltype(a + b) // C++11 의 해결책

auto Add(T1 a, T2 b) // C++14. 함수 반환값으로 auto만 사용가능
{
    return a + b ;
}


int main()
{
    std::cout << Add(1, 3.4) << std::endl;

//    a = 10; // error
//    int a;
//    a = 10; //ok
}

template function의 경우 위의 경우를 보면 알 수 있듯 반환 타입으로 auto를 설정한다. 하지만, 인자에 따른 적절한 타입을 반환하고 싶은 경우 decltype을 이용하여 타입을 설정할 수 있다. 하지만 decltype의 경우 컴파일 시간에 타입이 정해져야 하므로 경우에 따라 컴파일러가 오류를 발생시킬 수 있다. 이를 방지하기 위하여 template함수에 -> decltype(...)을 이용하여 템플릿 함수의 반환 타입인 auto에 대한 후행 반환타입(Trailing return type)을 정의할 수 있도록 C++11 표준에서 정의하고 있다.

반응형