티스토리 뷰

Macros are a text substitution mechanism.

Templates are a functional turing-complete language that is executed at compile time and is integrated into the C++ type system. You can think of them as a plugin mechanism for the language.

-------------------

They are parsed by the compiler and not by a preprocessor that runs before the compiler.

Here's what MSDN says about it: http://msdn.microsoft.com/en-us/library/aa903548(VS.71).aspx

Here are some problems with the macro:

  • There is no way for the compiler to verify that the macro parameters are of compatible types.
  • The macro is expanded without any special type checking.
  • The i and j parameters are evaluated twice. For example, if either parameter has a postincremented variable, the increment is performed two times.
  • Because macros are expanded by the preprocessor, compiler error messages will refer to the expanded macro, rather than the macro definition itself. Also, the macro will show up in expanded form during debugging.

If that's not enough for you, I don't know what is.

-------------------

There's a lot of comments here trying to differentiate macros and templates.

Yes - they are both the same thing: Code generation tools.

Macros are a primitive form, without much compiler enforcement (like doing Objects in C - it can be done, but it's not pretty). Templates are more advanced, and have a lot better compiler type-checking, error messages, etc.

However, each has strengths that the other does not.

Templates can only generate dynamic class types - macros can generate almost any code you want (other than another macro definition). Macros can be very useful to embed static tables of structured data into your code.

Templates on the other hand can accomplish some truly FUNKY things that are not possible with macros. For example:

template<int d,int t> class Unit
{
    double value;
    public:
        Unit(double n)
            {
                    value = n;
                        }
                            Unit<d,t> operator+(Unit<d,t> n)
                                {
                                        return Unit<d,t>(value + n.value);
                                            }
                                                Unit<d,t> operator-(Unit<d,t> n)
                                                    {
                                                            return Unit<d,t>(value - n.value);
                                                                }
                                                                    Unit<d,t> operator*(double n)
                                                                        {
                                                                                return Unit<d,t>(value * n);
                                                                                    }
                                                                                        Unit<d,t> operator/(double n)
                                                                                            {
                                                                                                    return Unit<d,t>(value / n);
                                                                                                        }
                                                                                                            Unit<d+d2,t+t2> operator*(Unit<d2,t2> n)
                                                                                                                {
                                                                                                                        return Unit<d+d2,t+t2>(value * n.value);
                                                                                                                            }
                                                                                                                                Unit<d-d2,t-t2> operator/(Unit<d2,t2> n)
                                                                                                                                    {
                                                                                                                                            return Unit<d-d2,t-t2>(value / n.value);
                                                                                                                                                }
                                                                                                                                                    etc....
                                                                                                                                                    };
                                                                                                                                                    
                                                                                                                                                    #define Distance Unit<1,0>
                                                                                                                                                    #define Time     Unit<0,1>
                                                                                                                                                    #define Second   Time(1.0)
                                                                                                                                                    #define Meter    Distance(1.0)
                                                                                                                                                    
                                                                                                                                                    void foo()
                                                                                                                                                    {
                                                                                                                                                       Distance moved1 = 5 * Meter;
                                                                                                                                                          Distance moved2 = 10 * Meter;
                                                                                                                                                             Time time1 = 10 * Second;
                                                                                                                                                                Time time2 = 20 * Second;
                                                                                                                                                                   if ((moved1 / time1) == (moved2 / time2))
                                                                                                                                                                          printf("Same speed!");
                                                                                                                                                                          }
                                                                                                                                                                          

The template allows the compiler to dynamically create and use type-safe instances of the template on-the-fly. The compiler actually does the template-parameter math at compile time, creating separate classes where needed for each unique result. There is an implied Unit<1,-1> (distance / time = velocity) type that is created and compared within the conditional, but never explicitly declared in code.

Apparently, someone at a university has defined a template of this sort with 40+ parameters (need a reference), each representing a different physics unit type. Think about the type-safety of that sort of class, just for your numbers.

-------------------

The answer is so long I can't sum up everything but:

  • for instance macros don't ensure type safety while function templates do: there is no way for the compiler to verify that the macro parameters are of compatible types -- also at the time the function template is instantiated the compiler knows whether int or float define operator +
  • templates open the door for metaprogramming (in short, evaluating things and taking decision at compile time): at compile time it's possible to know whether a type is integral or floating point; whether it's a pointer or whether it's const qualified, etc... see "type traits" in upcoming c++0x
  • class templates have partial specialization
  • function templates have explicit full specialization, in your example add<float>(5, 3); could be implemented differently than add<int>(5, 3); which isn't possible with macros
  • macro don't have any scope
  • #define min(i, j) (((i) < (j)) ? (i) : (j)) - the i and j parameters are evaluated twice. For example, if either parameter has a postincremented variable, the increment is performed two times
  • because macros are expanded by the preprocessor, compiler error messages will refer to the expanded macro, rather than the macro definition itself. Also, the macro will show up in expanded form during debugging
  • etc...

Note: In some rare cases, I preferred relying on variadic macros because there is no such thing as variadic templates until c++0x becomes mainstream. C++11 is live.

References:

  • C++ FAQ Lite: [35] Templates
  • Advantages of Templates
  • Templates vs. Macros (C++)

-------------------

On a very basic level, yes, template's are just macro replacements. But you're skipping out on a lot of things by thinking about it that way.

Consider template specialization, which to my knowledge you can't simulate with macro's. Not only does that allow, well, special implementation for certain types, it's one of the key parts in template meta-programming:

template <typename T>
struct is_void
{
    static const bool value = false;
    }
    
    template <>
    struct is_void<void>
    {
        static const bool value = true;
        }
        

Which in itself is just one example of the many things you can do. Templates themselves are Turing-complete.

This ignores the very basic things, such as scope, type-safety, and that macro's are messier.

-------------------

NO. One simple counter example: templates abide to namespaces, macro's ignore namespaces (as they are preprocessor statements).

namespace foo {
    template <class NumberType>
        NumberType add(NumberType a, NumberType b)
            {
                    return a+b;
                        }
                        
                            #define ADD(x, y) ((x)+(y))
                            } // namespace foo
                            
                            namespace logspace 
                            {
                                // no problemo
                                    template <class NumberType>
                                        NumberType add(NumberType a, NumberType b)
                                            {
                                                    return log(a)+log(b);
                                                        }
                                                        
                                                            // redefintion: warning/error/bugs!
                                                                #define ADD(x, y) (log(x)+log(y))
                                                                
                                                                } // namespace logspace
                                                                

-------------------
C ++ 템플릿은 이미 구문 분석 된 코드 버전에서 작동하고 컴파일 타임에 임의의 코드를 생성 할 수 있다는 점에서 Lisp 매크로 (C 매크로가 아님)와 비슷합니다. 안타깝게도 원시 Lambda 미적분과 유사한 것으로 프로그래밍하고 있으므로 반복과 같은 고급 기술은 다소 번거 롭습니다. 자세한 내용 은 Krysztof Czarnecki 및 Ulrich Eisenecker의

Generative Programming

참조하십시오 .-------------------
이 주제에 대해 좀 더 심층적 인 처리를 원하신다면, 모두가

좋아하는 C ++ 싫어하는

사람을 소개해 드릴 수 있습니다 . 이 사람은 내가 꿈꾸는 것보다 더 많은 C ++를 알고 싫어합니다. 이것은 동시에 FQA를 엄청나게 자극적이고 훌륭한 자원으로 만듭니다.-------------------

  • 템플릿은 형식이 안전합니다.
  • 템플릿 객체 / 유형은 네임 스페이스가 될 수 있고, 클래스의 개인 멤버가 될 수 있습니다.
  • 템플릿 함수에 대한 매개 변수는 함수 본문 전체에 복제되지 않습니다.

이것은 정말 큰 문제이며 수많은 버그를 방지합니다.-------------------
아니요, 불가능합니다. 전처리 기는 T의 컨테이너와 같은 몇 가지 작업에 (거의) 충분하지만 템플릿이 할 수있는 다른 작업에는 충분하지 않습니다.실제 예제를 보려면

Modern C ++ Programming

, Andre Alexandrescu 또는 Dave Abrahams 및 Aleksey Gurtovoy의

C ++ Metaprogramming

을 읽어보십시오. 어느 책에서든 거의 아무것도 전처리기를 사용하여 극도로 최소한의 수준으로 시뮬레이션 할 수 없습니다.편집 :

typename

한 가지 요구 사항은 매우 간단합니다. 컴파일러는 종속 이름이 유형을 참조하는지 여부를 항상 파악할 수 없습니다. 을 사용

typename

하면 컴파일러가 유형을 참조한다는 것을 명시 적으로 알 수 있습니다.

struct X { 
    int x;
    };
    
    struct Y {
        typedef long x;
        };
        
        template <class T>
        class Z { 
            T::x;
            };
            
            Z<X>; // T::x == the int variable named x
            Z<Y>; // T::x == a typedef for the type 'long'
            

typename

컴파일러에게 특정 이름이 변수 / 값이 아닌 유형을 참조하기위한 것임을 알려줍니다. 따라서 (예를 들어) 해당 유형의 다른 변수를 정의 할 수 있습니다.-------------------
언급되지 않은 것은 템플릿 함수가 매개 변수 유형을 추론 할 수 있다는 것입니다.

템플릿 <typename T>
무효 func (T t)
{
  T make_another = t;
  

다가오는 "typeof"연산자가이를 수정할 수 있지만 다른 템플릿을 분리 할 수는 없다고 주장 할 수 있습니다.

템플릿 <typename T>
void func (container <T> c)

또는:

템플릿 <tempate <typename> 클래스 컨테이너, typename T>
void func (Container <T> ct)

나는 또한 전문화의 주제가 충분히 다루어지지 않았다고 느낍니다. 다음은 매크로로 할 수없는 간단한 예입니다.

템플릿 <typename T>
T 분 (T a, TB)
{
  반환 a <b? a : b;
  }
  
  템플릿 <>
  char * min (char * a, char * b)
  {
    if (strcmp (a, b) <0)
        반환 a;
          그밖에
              반환 b;
              }
              

공간이 너무 작아서 유형 전문화에 들어갈 수 없지만 제가 아는 한 당신이 할 수있는 일은 정말 놀랍습니다.-------------------

이 답변은 C 전처리기에 대한 설명과 일반 프로그래밍에 사용되는 방법을 알려줍니다.


그들은 유사한 의미를 가능하게하므로 어떤면에서 그렇습니다. C 전처리 기는 일반 데이터 구조 및 알고리즘을 활성화하는 데 사용되었습니다 (

토큰 연결

참조 ). 그러나 C ++ 템플릿의 다른 기능을 고려하지 않으면 전체 일반 프로그래밍 게임 을 읽고 구현하기가

훨씬 더 명확

해집니다.누군가 하드 코어 C 전용 일반 프로그래밍이 작동하는 것을보고 싶다면

libevent

소스 코드를 읽으

십시오

. 여기 에서도 언급 됩니다 . 방대한 컨테이너 / 알고리즘 모음이 구현되고

SINGLE

헤더 파일 에서 수행 됩니다 (매우 읽기 쉬운). 나는 이것을 정말로 존경한다. C ++ 템플릿 코드 (다른 속성을 선호한다)는 매우 장황하다.-------------------
원시적 인 예를 들어 보자. 중히 여기다

#define min(a,b) ((a)<(b))?(a):(b)

다음으로 호출

c = min(a++,++b);

물론 실제 차이는 더 깊지 만 매크로와의 유사성을 버리기에 충분합니다.

편집

: 그리고 아니오, 매크로로 유형 안전을 보장 할 수 없습니다.

min()

비교 미만 (즉

operrator<

)을 정의하는 모든 유형에 대해 typesafe 어떻게 구현 합니까?-------------------
템플릿은 형식이 안전합니다. 정의를 사용하면 컴파일되지만 여전히 제대로 작동하지 않는 코드를 가질 수 있습니다.컴파일러가 코드에 도달하기 전에 매크로가 확장됩니다. 즉, 확장 된 코드에 대한 오류 메시지가 표시되고 디버거는 확장 된 버전 만 볼 수 있습니다.매크로를 사용하면 항상 일부 표현식이 두 번 평가 될 가능성이 있습니다. ++ x와 같은 것을 매개 변수로 전달한다고 상상해보십시오.-------------------
템플릿은 네임 스페이스에 넣거나 클래스의 멤버가 될 수 있습니다. 매크로는 전처리 단계 일뿐입니다. 기본적으로 템플릿은 다른 모든 것들과 잘 어울리는 언어의 일급 멤버입니다.-------------------
템플릿은 매크로 전처리 기가 할 수있는 것보다 훨씬 더 많은 일을 할 수 있습니다.예를 들어 템플릿 전문화가 있습니다.

이 템플릿이이 유형 또는 상수로 인스턴스화 된 경우 기본 구현을 사용하지 않는 것보다 여기에 있습니다.

... 템플릿은 일부 매개 변수의 유형이 동일하도록 강제 할 수 있습니다.


다음은 몇 가지 소스입니다.

  • Vandervoorde 및 Jossutis의 C ++ 템플릿 . 이 책은 내가 아는 템플릿에 대한 가장 훌륭하고 완전한 책입니다.
  • 부스트 라이브러리 는 거의 전적으로 템플릿 정의로 구성됩니다.

-------------------
제 생각에는 매크로는 C의 나쁜 습관입니다. 일부에게는 유용 할 수 있지만 typedef와 템플릿이있을 때 매크로가 실제로 필요하다고 생각하지 않습니다. 템플릿은 객체 지향 프로그래밍의 자연스러운 연속입니다. 템플릿으로 더 많은 일을 할 수 있습니다 ...이걸 고려하세요...

int main()
{
    SimpleList<short> lstA;
        //...
            SimpleList<int> lstB = lstA; //would normally give an error after trying to compile
            }
            

변환을 수행하기 위해 변환 생성자 및 시퀀스 생성자 (마지막 참조)라는 것을 목록에 대한 완전한 예제와 함께 사용할 수 있습니다.

#include <algorithm>

template<class T>
class SimpleList
{
public:
    typedef T value_type;
        typedef std::size_t size_type;
        
        private:
            struct Knot
                {
                        value_type val_;
                                Knot * next_;
                                        Knot(const value_type &val)
                                                :val_(val), next_(0)
                                                        {}
                                                            };
                                                                Knot * head_;
                                                                    size_type nelems_;
                                                                    
                                                                    public:
                                                                        //Default constructor
                                                                            SimpleList() throw()
                                                                                :head_(0), nelems_(0)
                                                                                    {}
                                                                                        bool empty() const throw()
                                                                                            { return size() == 0; }
                                                                                                size_type size() const throw()
                                                                                                    { return nelems_; }
                                                                                                    
                                                                                                    private:
                                                                                                        Knot * last() throw() //could be done better
                                                                                                            {
                                                                                                                    if(empty()) return 0;
                                                                                                                            Knot *p = head_;
                                                                                                                                    while (p->next_)
                                                                                                                                                p = p->next_;
                                                                                                                                                        return p;
                                                                                                                                                            }
                                                                                                                                                            
                                                                                                                                                            public:
                                                                                                                                                                void push_back(const value_type & val)
                                                                                                                                                                    {
                                                                                                                                                                            Knot *p = last();
                                                                                                                                                                                    if(!p)
                                                                                                                                                                                                head_ = new Knot(val);
                                                                                                                                                                                                        else
                                                                                                                                                                                                                    p->next_ = new Knot(val);
                                                                                                                                                                                                                            ++nelems_;
                                                                                                                                                                                                                                }
                                                                                                                                                                                                                                    void clear() throw()
                                                                                                                                                                                                                                        {
                                                                                                                                                                                                                                                while(head_)
                                                                                                                                                                                                                                                        {
                                                                                                                                                                                                                                                                    Knot *p = head_->next_;
                                                                                                                                                                                                                                                                                delete head_;
                                                                                                                                                                                                                                                                                            head_ = p;
                                                                                                                                                                                                                                                                                                    }
                                                                                                                                                                                                                                                                                                            nelems_ = 0;
                                                                                                                                                                                                                                                                                                                }
                                                                                                                                                                                                                                                                                                                    //Destructor:
                                                                                                                                                                                                                                                                                                                        ~SimpleList() throw()
                                                                                                                                                                                                                                                                                                                            { clear(); }
                                                                                                                                                                                                                                                                                                                                //Iterators:
                                                                                                                                                                                                                                                                                                                                    class iterator
                                                                                                                                                                                                                                                                                                                                        {
                                                                                                                                                                                                                                                                                                                                                Knot * cur_;
                                                                                                                                                                                                                                                                                                                                                    public:
                                                                                                                                                                                                                                                                                                                                                            iterator(Knot *p) throw()
                                                                                                                                                                                                                                                                                                                                                                    :cur_(p)
                                                                                                                                                                                                                                                                                                                                                                            {}
                                                                                                                                                                                                                                                                                                                                                                                    bool operator==(const iterator & iter)const throw()
                                                                                                                                                                                                                                                                                                                                                                                            { return cur_ == iter.cur_; }
                                                                                                                                                                                                                                                                                                                                                                                                    bool operator!=(const iterator & iter)const throw()
                                                                                                                                                                                                                                                                                                                                                                                                            { return !(*this == iter); }
                                                                                                                                                                                                                                                                                                                                                                                                                    iterator & operator++()
                                                                                                                                                                                                                                                                                                                                                                                                                            {
                                                                                                                                                                                                                                                                                                                                                                                                                                        cur_ = cur_->next_;
                                                                                                                                                                                                                                                                                                                                                                                                                                                    return *this;
                                                                                                                                                                                                                                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    iterator operator++(int)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        iterator temp(*this);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    operator++();
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                return temp;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                value_type & operator*()throw()
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        { return cur_->val_; }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                value_type operator*() const
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        { return cur_->val_; }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                value_type operator->()
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        { return cur_->val_; }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                const value_type operator->() const
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        { return cur_->val_; }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            };
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                iterator begin() throw()
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    { return iterator(head_); }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        iterator begin() const throw()
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            { return iterator(head_); }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                iterator end() throw()
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    { return iterator(0); }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        iterator end() const throw()
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            { return iterator(0); }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                //Copy constructor:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    SimpleList(const SimpleList & lst)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        :head_(0), nelems_(0)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    for(iterator i = lst.begin(); i != lst.end(); ++i)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                push_back(*i);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        void swap(SimpleList & lst) throw()
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    std::swap(head_, lst.head_);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            std::swap(nelems_, lst.nelems_);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    SimpleList & operator=(const SimpleList & lst)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                SimpleList(lst).swap(*this);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        return *this;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                //Conversion constructor
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    template<class U>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        SimpleList(const SimpleList<U> &lst)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            :head_(0), nelems_(0)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        for(typename SimpleList<U>::iterator iter = lst.begin(); iter != lst.end(); ++iter)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    push_back(*iter);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            template<class U>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                SimpleList & operator=(const SimpleList<U> &lst)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            SimpleList(lst).swap(*this);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    return *this;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            //Sequence constructor:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                template<class Iter>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    SimpleList(Iter first, Iter last)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        :head_(0), nelems_(0)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    for(;first!=last; ++first)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                push_back(*first);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    };
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    

 

템플릿에서 cplusplus.com

정보를 확인하십시오 ! 템플릿을 사용하여 유형 등에 대한 일종의 문서가 사용되는 특성이라고하는 작업을 수행 할 수 있습니다. 템플릿으로 훨씬 더 많은 일을 할 수 있고 매크로로 가능한 것보다 훨씬 더 많은 일을 할 수 있습니다!-------------------
typename 키워드는 문맥없이 중첩 된 typdef를 활성화하기 위해 제공됩니다. 이는 메타 데이터를 유형 (특히 포인터와 같은 내장 유형)에 추가 할 수있는 특성 기술에 필요했으며, STL을 작성하는 데 필요했습니다. 그렇지 않으면 typename 키워드는 class 키워드와 동일합니다.-------------------
템플릿

은 데이터 유형을 이해합니다.

매크로는 그렇지 않습니다.이것은 다음과 같은 일을 할 수 있음을 의미합니다.

  • 모든 데이터 유형을 취할 수 있는 연산 (예 : 숫자래핑 하는 작업)을 정의한 다음 데이터 유형이 정수인지 부동 소수점인지에 따라 적절한 알고리즘을 선택하는 특수화를 제공합니다.
  • 컴파일 타임에 데이터 유형의 측면을 결정하여 Microsoft가 strcpy_s 및 ilk 의 C ++ 오버로드에 사용하는 배열 크기의 템플릿 추론 과 같은 트릭을 허용 합니다.

또한 템플릿은 유형에 안전하기 때문에 가상의 고급 전처리기로 수행 할 수 있지만 기껏해야 복잡하고 오류가 발생하기 쉬운 템플릿 코딩 기술이 많이 있습니다 (예 :

템플릿 템플릿 매개 변수

, 기본 템플릿 인수, 정책 템플릿

Modern C ++ Design

에서 논의 됨 ).-------------------
매크로에는 몇 가지 기본적인 문제가 있습니다.첫째, 그들은 범위 나 유형을 존중하지 않습니다. 내가 가지고 있다면 내 프로그램에

#define max(a, b)...

토큰이있을 때마다

max

어떤 이유로 든 대체됩니다. 변수 이름이거나 중첩 범위 내 깊은 곳이면 대체됩니다. 이로 인해 찾기 어려운 컴파일 오류가 발생할 수 있습니다. 반대로 템플릿은 C ++ 유형 시스템 내에서 작동합니다. 템플릿 함수는 범위 내에서 이름을 재사용 할 수 있으며 변수 이름을 다시 쓰려고 시도하지 않습니다.둘째, 매크로는 다양 할 수 없습니다. 템플릿

std::swap

은 일반적으로 임시 변수를 선언하고 명백한 할당을 수행합니다. 이것이 일반적으로 작동하는 명백한 방법이기 때문입니다. 그것이 매크로가 제한되는 것입니다. 이는 큰 벡터의 경우 매우 비효율적이므로 벡터에는

swap

전체 내용이 아닌 참조를 교체 하는 특수 기능 이 있습니다. (이것은 일반 C ++ 프로그래머가 작성해서는 안되지만 사용하는 것에서 매우 중요한 것으로 밝혀졌습니다.)셋째, 매크로는 어떤 형태의 유형 추론도 할 수 없습니다. 유형의 변수를 선언해야하고 유형이 무엇인지 알지 못하기 때문에 처음에는 제네릭 스왑 매크로를 작성할 수 없습니다. 템플릿은 유형을 인식합니다.템플릿의 강력한 기능을 보여주는 한 가지 좋은 예는 원래 표준 템플릿 라이브러리라고 불렸던 것입니다.이 라이브러리는 컨테이너, 알고리즘 및 반복기로 표준에 있습니다. 작동 방식을 살펴보고 매크로로 대체 할 방법을 생각해보십시오. Alexander Stepanov는 STL 아이디어를 구현하기 위해 다양한 언어를 살펴 보았고 템플릿이있는 C ++만이 작동 할 것이라고 결론지었습니다.-------------------
템플릿은 가장 기본적인 기능에서 매크로와 유사합니다. 결국 템플릿은 매크로 대신 "문명화 된"대안으로 언어에 도입되었습니다. 그러나 가장 기본적인 기능에 관해서도 유사점은 피부 깊이입니다.그러나 전문화 (부분적 또는 명시 적)와 같은 템플릿의 고급 기능에 도달하면 매크로와의 명백한 유사성이 완전히 사라집니다.-------------------
템플릿 매개 변수가 유형 검사되고 매크로에 비해 템플릿의 많은 장점이 있지만 템플릿은 여전히 ​​텍스트 대체를 기반으로한다는 점에서 매크로와 매우 유사합니다. 컴파일러는 대체 할 유형 매개 변수를 제공 할 때까지 템플릿 코드가 의미가 있는지 확인하지 않습니다. Visual C ++는 실제로 호출하지 않는 한이 함수에 대해 불평하지 않습니다.

template<class T>
void Garbage(int a, int b)
{
    fdsa uiofew & (a9 s) fdsahj += *! wtf;
    }
    

편집 :

이 예제는 Visual C ++에만 적용됩니다. 에서

표준

템플릿 이제까지 사용되기 전에 예는 GCC 또는 연타를 VC에 의해 허용 ++하지만되지 않도록 C ++ 템플릿 코드는 실제로 구문 트리에 구문 분석됩니다. (저는 VC ++ 코드를 GCC로 포팅하려고 할 때 이것을 배웠고 특수화되지 않은 템플릿에서 수백 개의 구문 오류를 처리해야했습니다.) 그러나 구문 트리가 여전히 의미

상 의미

가있는 것은 아닙니다 . 컴파일러에 관계없이 .NET Framework를 제공하여 템플릿을 인스턴스화 할 때까지 본문에서 유형 검사가 발생하지 않습니다

<template arguments>

.따라서 일반적으로 템플릿이 허용하도록 설계된 형식 매개 변수의 지정된 범주에 대해 템플릿 코드가 올바르게 작동하는지 또는 성공적으로 컴파일되는지 알 수 없습니다.-------------------
이것은 이미 언급 된 답변의 결과만큼 답변이 아닙니다. 프로그래밍이 필요한 과학자, 외과 의사, 그래픽 아티스트 및 기타 전문가와 함께 작업하지만 전문적인 풀 타임 소프트웨어 개발자는 아니며 앞으로도 아닐 것입니다. 매크로는 가끔 프로그래머가 쉽게 이해할 수있는 반면 템플릿은 더 높은 수준을 요구하는 것으로 보입니다. C ++ 프로그래밍 경험이 더 깊고 지속적인 경우에만 가능한 추상적 인 사고 수준. 템플릿이 유용한 개념 인 코드로 작업하는 많은 인스턴스가 필요합니다. 개념이 사용하기에 충분히 의미가 있습니다. 모든 언어 기능에 대해 말할 수 있지만 템플릿에 대한 경험의 양은 전문 캐주얼 프로그래머가 일상적인 작업에서 얻을 수있는 것보다 더 큰 격차를 나타냅니다.평균적인 천문학 자 또는 전자 공학자는 아마도 매크로를 잘 이해하고 매크로를 피해야하는 이유를 이해할 수도 있지만 일상적인 사용에 충분할만큼 템플릿을 잘 사용하지는 않을 것입니다. 그런 맥락에서 매크로가 실제로 더 좋습니다. 당연히 예외가 많이 있습니다. 일부 물리학 자들은 프로 소프트웨어 엔지니어를 중심으로 원을 그리지 만 이것은 일반적이지 않습니다.-------------------
템플릿은 어느 정도의 유형 안전성을 제공합니다.-------------------
템플릿은 언어로 통합되며 형식이 안전합니다.매크로로이 작업을 수행하는 방법을 알려주십시오. 이것은 무거운 템플릿 메타 프로그래밍입니다.

https://www.youtube.com/watch?v=0A9pYr8wevk

매크로 AFAIK는 템플릿 부분 전문화가 수행 할 수있는 방식으로 유형을 계산할 수 없다고 생각합니다.

출처
https://stackoverflow.com/questions/1902578

댓글
공지사항
Total
Today
Yesterday
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31