Solved

how can i use the template in Separation Model??

Posted on 2003-10-29
4
275 Views
Last Modified: 2010-04-02
//Array.h
#include <iostream>
using std::ostream;
using std::cout;
using std::endl;

template <class elemType> class Array;
template <class elemType> ostream&
          operator<<( ostream &, Array<elemType> & );

template <class elemType>
class Array {
public:
    // explicit Array( int sz = DefaultArraySize )
    Array( int sz = DefaultArraySize )
         { init( 0, sz ); }

    Array( const elemType *ar, int sz )
         { init( ar, sz ); }

    Array( const Array &iA )
         { init( iA._ia, iA._size ); }

    virtual ~Array() { delete[] _ia; }

    Array& operator=( const Array & );
    int size() const { return _size; }

    virtual elemType& operator[]( int ix ) { return _ia[ix]; }
    virtual elemType  operator[]( int ix ) const { return _ia[ix]; }

    elemType at( int ix ) const { return _ia[ ix ]; }

    virtual ostream &print( ostream& os = cout ) const;
    virtual void grow();

protected:
    void init( const elemType*, int );

    // static const int DefaultArraySize = 12;
    static const int DefaultArraySize;
    int       _size;
    elemType *_ia;
};

template <class Type>
        Type min( Type a, Type b ) {
                return a < b ? a : b;
}

template <class elemType>
        void swap( Array<elemType> &array, int i, int j )
{
        elemType tmp = array[ i ];
        array[ i ] = array[ j ];
        array[ j ] = tmp;
}

//Array.cpp
#include "array.h"
#include <cassert>

template <class elemType>
  const int Array<elemType>::DefaultArraySize = 12;

template <class elemType>
    void Array<elemType>::init( const elemType *array, int sz )
{
    if ( ! array ) { _size = 0; _ia = 0; }
    if ( sz < 1 ) sz = 1;

    _size = sz;
    _ia = new elemType[ _size ];

    if ( ! array ) return;

    for ( int ix = 0; ix < _size; ++ix )
       _ia[ ix ] = array[ ix ];
}

template <class elemType> Array<elemType>&
    Array<elemType>::operator=( const Array<elemType> &iA )
{
    if ( this == &iA )
         return *this;

    delete[] _ia;
    init( iA._ia, iA._size );
    return *this;
}

template <class elemType> ostream&
    operator<<( ostream &os, Array<elemType> &ar )
{
    return ar.print( os );
}

template <class elemType>
    ostream& Array<elemType>::print( ostream &os ) const
{
    const int lineLength = 12;
    os << "( " << _size << " )< ";

    for ( int ix = 0; ix < _size; ++ix )
    {
          if ( ix % lineLength == 0 && ix )
               os << "\n\t";

          os << _ia[ ix ];
          // don't generate comma for last item on line
          // nor for the last element of the array
          if ( ix % lineLength != lineLength-1 && ix != _size-1 )
               os << ", ";
    }

    os << " >\n";
    return os;
}

template <class elemType>
    void Array<elemType>::grow()
{
    elemType *oldia = _ia;
    int oldSize = _size;

    _size = oldSize + oldSize/2 + 1;
    _ia   = new elemType[_size];

    int ix;
    for ( ix = 0; ix < oldSize; ++ix)
          _ia[ix] = oldia[ix];

    for ( ; ix < _size; ++ix )
       _ia[ix] = elemType();

    delete[] oldia;
}

//Algo.cpp
template <class elemType>
        void sort( Array<elemType> &array, int low, int high ) {
        if ( low < high ) {
                int lo = low;
                int hi = high + 1;
                elemType elem = array[lo];

                for (;;) {
                        while ( min( array[++lo], elem ) != elem && lo < high ) ;
                        while ( min( array[--hi], elem ) == elem && hi > low ) ;

                        if (lo < hi)
                                swap( array, lo, hi );
                        else break;
                }

                swap( array, low, hi );
                sort( array, low, hi-1 );
                sort( array, hi+1, high );
        }
}

template <class elemType>
        void display( Array<elemType> &array )
{ // display format: < 0 1 2 3 4 5 >

        cout << "< ";
        for ( int ix = 0; ix < array.size(); ++ix )
                cout << array[ix] << " ";
        cout << ">\n";
}

//the main program
#include <string>
using std::string;

#include "Array.h"
#include "Algo.cpp"

double da[10] = {
        26.7, 5.7, 37.7, 1.7, 61.7, 11.7, 59.7,
        15.7, 48.7, 19.7 };

int ia[16] = {
        503, 87, 512, 61, 908, 170, 897, 275, 653,
        426, 154, 509, 612, 677, 765, 703 };

string sa[11] = {
        "a", "heavy", "snow", "was", "falling", "when",
        "they", "left", "the", "police", "station" };

int main() {

        // call the constructor to initialize arrd
        Array<double> arrd( da, sizeof(da)/sizeof(da[0]) );

        // call the constructor to initialize arri
        Array<int> arri( ia, sizeof(ia)/sizeof(ia[0]) );

        // call the constructor to initialize arrs
        Array<string> arrs( sa, sizeof(sa)/sizeof(sa[0]) );

        cout << "sort array of doubles (size == "
             << arrd.size() << ")" << endl;
        sort(arrd, 0, arrd.size()-1 );
        display(arrd);

        cout << "sort array of ints (size == "
             << arri.size() << ")" << endl;
        sort(arri, 0, arri.size()-1 );
        display(arri);

        cout << "sort array of strings (size == "
             << arrs.size() << ")" << endl;
        sort(arrs, 0, arrs.size()-1 );
         display(arrs);

        return 0;
}
but so many messages:
Compiling...
main11.cpp
Linking...
main11.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall Array<double>::grow(void)" (?grow@?$Array@N@@UAEXXZ)
main11.obj : error LNK2001: unresolved external symbol "public: virtual class std::basic_ostream<char,struct std::char_traits<char> > & __thiscall Array<double>::print(class std::basic_ostream<char,struct std::char_traits<char> > &)const " (?print@?
$Array@N@@UBEAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV23@@Z)
main11.obj : error LNK2001: unresolved external symbol "protected: void __thiscall Array<double>::init(double const *,int)" (?init@?$Array@N@@IAEXPBNH@Z)
main11.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall Array<int>::grow(void)" (?grow@?$Array@H@@UAEXXZ)
main11.obj : error LNK2001: unresolved external symbol "public: virtual class std::basic_ostream<char,struct std::char_traits<char> > & __thiscall Array<int>::print(class std::basic_ostream<char,struct std::char_traits<char> > &)const " (?print@?$Ar
ray@H@@UBEAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV23@@Z)
main11.obj : error LNK2001: unresolved external symbol "protected: void __thiscall Array<int>::init(int const *,int)" (?init@?$Array@H@@IAEXPBHH@Z)
main11.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall Array<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::grow(void)" (?grow@?$Array@V?$basic_string@DU?$char_traits@D@std
@@V?$allocator@D@2@@std@@@@UAEXXZ)
main11.obj : error LNK2001: unresolved external symbol "public: virtual class std::basic_ostream<char,struct std::char_traits<char> > & __thiscall Array<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::print
(class std::basic_ostream<char,struct std::char_traits<char> > &)const " (?print@?$Array@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@@UBEAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV23@@Z)
main11.obj : error LNK2001: unresolved external symbol "protected: void __thiscall Array<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::init(class std::basic_string<char,struct std::char_traits<char>,class
 std::allocator<char> > const *,int)" (?init@?$Array@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@@IAEXPBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@Z)
Debug/main11.exe : fatal error LNK1120: 9 unresolved externals
Error executing link.exe.

main11.exe - 10 error(s), 0 warning(s)

how can i use the template in Separation Model??

thanks!
0
Comment
Question by:weileng_ghost
  • 3
4 Comments
 
LVL 30

Expert Comment

by:Axter
ID: 9647022
You can not put the template code inside a *.cpp file.

You need to put it in the header.
0
 
LVL 30

Accepted Solution

by:
Axter earned 85 total points
ID: 9647068
In order to put the code inside the *.cpp file, your compiler has to support export keyword.

There's only one compiler that support this, and VC++ is not it.

The only other way to get around this, is to include forward template class declarations inside the *.cpp file that contains the template implementation.
template foo<int>; //Forward declaration of int type for foo


Example for your code:


//Algo.cpp

template Array<int>;
template Array<double>;
template Array<string>;
template Array<int>;

template <class elemType>
       void sort( Array<elemType> &array, int low, int high ) {
       if ( low < high ) {
               int lo = low;
               int hi = high + 1;
               elemType elem = array[lo];

               for (;;) {
                       while ( min( array[++lo], elem ) != elem && lo < high ) ;
                       while ( min( array[--hi], elem ) == elem && hi > low ) ;

                       if (lo < hi)
                               swap( array, lo, hi );
                       else break;
               }

               swap( array, low, hi );
               sort( array, low, hi-1 );
               sort( array, hi+1, high );
       }
}

template <class elemType>
       void display( Array<elemType> &array )
{ // display format: < 0 1 2 3 4 5 >

       cout << "< ";
       for ( int ix = 0; ix < array.size(); ++ix )
               cout << array[ix] << " ";
       cout << ">\n";
}

0
 

Author Comment

by:weileng_ghost
ID: 9647824
ok,it works well.thanks a lot!!!
by the way,which compiler supports the separation Model?
0
 
LVL 30

Expert Comment

by:Axter
ID: 9649264
I forgot which one.  It was in the C++ Jornal magazine a few months ago.

I think it's either edg or Comeau
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now