• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 297,  comments - 15,  trackbacks - 0

            c++ class template header and implementation (skeleton) definitions are often hard to read, let alone to write. Especially when defining template classes that are derived from base template classes, I often find myself struggling for the correct syntax.

            In this article, I will present a template-based source code generator to produce C++ class template header implementation (skeleton) definitions in .hpp and .cpp files, based on a minimal yet functional set of methods.

            A template is a way to specify generic code, with a placeholder for the type. Note that the type is the only "parameter" of a template, but a very powerful one, since anything from a function to a class (or a routine) can be specified in "general" terms without concerning yourself about the specific type. Yet. These details are postponed until you start to use the template. You can consider templates to be compile-time polymorphic, yet typesafe (in contrast to C MACROs).

            Function vs. Class
            When talking about C++ templates, one should realize that there are, in fact, two kinds of templates: function templates and class templates. The former are quite easy to implement, because they usually only contain the template(s) in their definition. As an example of a function template, here is a function that produces the minimum of two arguments, without specifying the actual type of the arguments:

            template <typename T>
            T max(const T &X, const T &Y)
            {
            if (X > Y)
            return X;
            else
            return Y;
            }
            T is the usual template character that is used to specify the typename, which—at the time of definition—is unknown, and will be determined when you actually use the template in your source code. Here is an example:
            int x = max(6, 42); // compiler determines T = int
            float y = max(3.1415927, 2.20371); // compiler determines T = float
            Or explicitly, as follows:
            int x = max<int> (6, 42); // explicit template syntax
            The C++ compiler will be able to determine—at compile time—where the calls to this function template are made, which argument types are used, and hence which "expansions" of this function template have to be generated (like a MACRO expansion) and then compiled and linked into an executable. All this is happening behind the scenes, of course, although template expansion can take a lot of compiler and linker resource (as you may find out when you start to use them more often).

            Class templates are similar to function templates in that the compiler will determine at compile-time which expansions (or instantions) of the class template are needed. The fact that they are classes and not merely functions, makes the syntax a bit more difficult, however.

            Pop Quiz
            Even if you're an experienced C++ class template user, could you tell me from the top of your head what the syntax would be of the implementation skeleton for the copy constructor of a template class TDerived, which is derived from a template class TBase? You have 10 seconds ...

            It turns out to be as follows:

            template <class T> TDerived<T>::TDerived(const TDerived<T>& copy): TBase<T>(copy)
            But I don't blame you if you couldn't come up with that right away. If you did know the answer, then you probably don't need to read the remainder of this article, unless you're also interested in a template-based template header/source generator. That's what I made for myself, to help me remember.

            Canonical Class
            But before I want to continue with class templates, let's first talk about a minimum useful class, sometimes also called a canonical class. By this I mean a class definition which is minimal (only a few key methods), but still complete and useful. This means that the class should at least contain the default constructor (without an argument), the destructor, a copy constructor, the assignment operator, the compare operator and last—optionally—the stream operator (always useful when debugging). When a class contains at least these methods, we can call it a canonical class.

            Since I'm planning to produce a template header and source generator, it's important to realise what I should generate and what not. Making sure that I produce a canonical class—especially when it comes to templates, can make the difference between a nice but useless or an actual useful tool. As an example, here is the canonical class definition (header file) of a class TBase:

            class TBase
            {
            public:
            // Constructors & Destructors
            TBase(void);
            TBase(const TBase& copy);
            virtual ~TBase(void);

            // Operator overloading
            TBase& operator = (const TBase& other);
            int operator == (const TBase& other) const;

            // Output
            friend ostream& operator << (ostream& os, const TBase& other);
            };

            Canonical Class Template
            We can modify the listing above to turn it into a canonical template class definition. Just like function templates, this means we have to use the <T> template syntax in a few places, and sometimes in more than a few. Luckily, it's not that hard, and the result can be seen in the following listing:
            template <class T> class TBase
            {
            public:
            // Constructors & Destructors
            TBase(void);
            TBase(const TBase<T>& copy);
            virtual ~TBase(void);

            // Operator overloading
            TBase<T>& operator = (const TBase<T>& other);
            int operator == (const TBase<T>& other) const;

            // Output
            friend ostream& operator << (ostream& os, const TBase<T>& other);
            };

            Just to let you know what the implementation looks like (the empty
            skeletons, that is), take a look at the following listing:
            // Constructors & Destructors
            template <class T> TBase<T>::TBase(void) {}
            template <class T> TBase<T>::TBase(const TBase<T>& copy) {}
            template <class T> TBase<T>::~TBase(void) {}

            // Operator overloading
            template <class T> TBase<T>& TBase<T>::operator = (const TBase<T>& other) {}
            template <class T> int TBase<T>::operator == (const TBase<T>& other) const {}

            // Output
            template <class T> ostream& operator << (ostream& os, const TBase<T>& other) {}

            This is usually the place where I could do with a little help or support
            to get the class template syntax right.

            Derived Templates
            If you've been able to keep up with me so far, then let's get to the final round: templates derived from other templates. Sometimes you just have to derive your own custom class template TDerived from a base template class TBase (sound familiar?). And just for your amusement (and mine), I've included the header listing for the derived canonical class template definition below:

            template <class T> class TDerived: public TBase<T> { public: // Constructors & Destructors TDerived(void); TDerived(const TDerived<T>& copy); virtual ~TDerived(void); // Operator overloading TDerived<T>& operator = (const TDerived<T>& other); int operator == (const TDerived<T>& other) const; // Output friend ostream& operator << (ostream& os, const TDerived<T>& other); }; Certainly this TDerived class template definition needs a list of empty implementation skeletons, which are defined as follows (empty because they're skeletons, but they still need to be implemented by the programmer, of course). // Constructors & Destructors template <class T> TDerived<T>::TDerived(void): TBase<T>() {} template <class T> TDerived<T>::TDerived(const TDerived<T>& copy): TBase<T>(copy) {} template <class T> TDerived<T>::~TDerived(void) {} // Operator overloading template <class T> TDerived<T>& TDerived<T>::operator = (const TDerived<T>& other) {} template <class T> int TDerived<T>::operator == (const TDerived<T>& other) const {} // Output template <class T> ostream& operator << (ostream& os, const TDerived<T>& other) {} OK, who could already produce the above listing without a second thought? If you could, then you probably didn't need to read this article, because the fun stuff is over. What remains is the description of a little tool that I made for myself to actually produce and generate the output listings that we've seen so far.
            Template Template
            If you look closely at the listings presented so far, you can see a pattern (believe me, there is logic behind this class template syntax). In fact, I have been able to produce two template files that can be used to generate the template listings we've seen in this article. The template file for the class definition (typically inside a header file) is defined as follows:
            //    File: <#class>.hpp
            // Author: drs. Robert E. Swart>
            // Date: <#date>
            // Time: <#time>
            // Version: 0.01
            // Generated by: HeadGen (c) 1995-2001 by Bob Swart
            (aka Dr.Bob - www.drbob42.com)
            // Changes:
            //

            #ifndef <#class>_hpp
            #define <#class>_hpp

            #include <iostream.h>
            <#includebase>

            template <class <#templatechar>> class <#class> <#publicbase>
            {
            public:
            // Constructors & Destructors
            <#class>(void);
            <#class>(const <#class><#template>& copy);
            virtual ~<#class>(void);>

            // Accessing functions

            // Modifier functions

            // Operator overloading
            <#class><#template>& operator = (const <#class><#template>& other);
            int operator == (const <#class><#template>& other) const;

            // Streaming output
            friend ostream& operator << (ostream& os, const <#class><#template>& other);

            protected:
            private:
            };

            #endif

            Note the special #-tags. WebBroker developers may recognize these as
            tags used in the PageProducer components. That's actually the case,
            since I'm using a TPageProducer component (from the Internet tab) to
            expand the above template into a true class template definition
            header—with or without a template base class.
            The same technique can be applied to the following template listing,
            that can be used to produce the empty template skeleton implementations:
            // File: <#class>.cpp
            // Author: drs. Robert E. Swart
            // Date: <#date>
            // Time: <#time>
            // Version: 0.01
            // Generated by: HeadGen (c) 1995-2001 by Bob Swart
            (aka Dr.Bob - www.drbob42.com)
            // Changes:
            //

            #include "<#include>.hpp"

            // Constructors & Destructors
            template <class <#templatechar>> <#class><#template>::<#class>(void) <#base>
            <#body>

            template <class <#templatechar>> <#class><#template>::<#class>(const
            <#class><#template>& copy) <#basecopy>
            <#body>

            template <class <#templatechar>> <#class><#template>::~<#class>(void)
            <#body>

            // Operator overloading
            template <class <#templatechar>> <#class><#template>& <#class><#template>::operator = (const <
            #class><#template>& other)
            <#body>

            template <class <#templatechar>> int <#class><#template>::operator == (const
            <#class><#template>& other) const
            <#body>

            // Streaming output
            template <class <#templatechar>> ostream& operator << (ostream&
            os, const <#class><#template>& other)
            <#body>

            Again, the above listing can be used to produce a stand-alone class
            template as well as a derived class template. We only need to specify
            three options: the class name, the (optional) base class name, and the
            template character.

            HeadGen

             The utility HeadGen only requires the class name (the template character is T by default), as can be seen in Figure 1.

            For the base class, specify Base in the Class Name box leave the Ancestor type box empty, and click on Generate. For the derived class, specify Derived in the Class Name box, Base in the Ancestor Type box and then click on Generate again. In both cases, the T will be added as prefix automatically (files Base.hpp and Base.cpp will contain the definition for TBase).

            A very simple Borland C++Builder example program (to test the syntax of the generated files) can be seen below:

            //--------------------------------------------------------- #pragma hdrstop #include "Base.cpp" // TBase #include "Derived.cpp"; // TDerived //-------------------------------------------------------- typedef TDerived<int> TintClass; #pragma argsused int main(int argc, char* argv[]) { TintClass* Bob = new TintClass(); TintClass Swart = TintClass(*Bob); if (*Bob == Swart) { *Bob = Swart; } return 0; } //-------------------------------------------------------- Note that I needed to include the .cpp files of the templates, and not only (or just) the .hpp files. That's because the .cpp files are "expanded" (like MACROs) to the compiler, which must find them in order to be able to use them. External Templates
            The two template files are external files HeadGen.h (for the .hpp header) and HeadGen.c (for the .cpp source file). As an additional benefit, you can edit these templates and make sure your own copyright statements appear in them. Make sure to keep all #-tags intact, though, otherwise the template PageProducer won't be able to work correctly anymore.



            from:
            http://www.devx.com/cplus/Article/20689/0/page/1

            posted on 2010-04-19 11:05 chatler 閱讀(619) 評論(0)  編輯 收藏 引用 所屬分類: Template
            <2008年7月>
            293012345
            6789101112
            13141516171819
            20212223242526
            272829303112
            3456789

            常用鏈接

            留言簿(10)

            隨筆分類(307)

            隨筆檔案(297)

            algorithm

            Books_Free_Online

            C++

            database

            Linux

            Linux shell

            linux socket

            misce

            • cloudward
            • 感覺這個博客還是不錯,雖然做的東西和我不大相關,覺得看看還是有好處的

            network

            OSS

            • Google Android
            • Android is a software stack for mobile devices that includes an operating system, middleware and key applications. This early look at the Android SDK provides the tools and APIs necessary to begin developing applications on the Android platform using the Java programming language.
            • os161 file list

            overall

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            亚洲精品无码久久久久AV麻豆| 久久水蜜桃亚洲av无码精品麻豆| 亚洲精品乱码久久久久66| Xx性欧美肥妇精品久久久久久 | 国产免费福利体检区久久| 久久AV高清无码| 久久99精品久久久久久hb无码| 久久精品国产日本波多野结衣| 色8激情欧美成人久久综合电| 精品国产综合区久久久久久| 99久久成人18免费网站| 欧美综合天天夜夜久久| 免费观看成人久久网免费观看| .精品久久久麻豆国产精品| 精品999久久久久久中文字幕| 国产V综合V亚洲欧美久久| 国产午夜久久影院| 精品久久久久久国产免费了| 久久九九免费高清视频| 一本大道久久香蕉成人网| 亚洲中文字幕无码久久精品1| 麻豆亚洲AV永久无码精品久久| 久久国产亚洲高清观看| 91久久香蕉国产熟女线看| 久久精品成人免费观看97| 久久亚洲精品无码aⅴ大香| 久久精品国产亚洲AV无码娇色| 94久久国产乱子伦精品免费| 久久国产精品免费一区| 亚洲综合精品香蕉久久网| 国产精品视频久久久| 久久青青草原亚洲av无码| 少妇内射兰兰久久| 狠狠色综合网站久久久久久久| 亚洲精品美女久久久久99小说| 日韩AV无码久久一区二区| 国内精品伊人久久久久影院对白 | 久久国产高清一区二区三区| 7777精品久久久大香线蕉| 91久久精品国产免费直播| 亚洲av成人无码久久精品|