hkBattousai
hkBattousai

Reputation: 10911

How to call a template method?

There are a lot of online documents explaining how to write template methods, but not much example about how to call them, how to use them in code.

I have a template method like this:

VectorConvertor.h

template <class T>
static void AppendToVector(std::vector<T> & VectorToBeAppended,
                           std::vector<T> & VectorToAppend);


VectorConvertor.cpp

template <class T>
void VectorConvertor::AppendToVector(std::vector<T> & VectorToBeAppended,
                                     std::vector<T> & VectorToAppend)
{
    for (std::vector::size_type i=0; i<VectorToAppend.size(); i++)
    {
        VectorToBeAppended.push_back(VectorToAppend.at(i));
    }
}

Usage attempt in code:

std::vector<uint8_t> InputData, OutputData;
// ...
VectorConvertor::AppendToVector(OutputData, InputData);


I compile this code without any error. But when I try to use this method I get the following errors:

error LNK1120: 1 unresolved externals

and

error LNK2019: unresolved external symbol "public: static void __cdecl VectorConvertor::AppendToVector(class std::vector > &,class std::vector > &)" (??$AppendToVector@E@VectorConvertor@@SAXAEAV?$vector@EV?$allocator@E@std@@@std@@0@Z) referenced in function "public: staticclass std::vector > __cdecl Utf8::WStringToUtf8(class std::basic_string,class std::allocator >)" (?WStringToUtf8@Utf8@@SA?AV?$vector@EV?$allocator@E@std@@@std@@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@3@@Z)


When I don't use this method in my code I don't get any error messages. What am I doing wrong while calling it? Am I missing something?


I'm using Visual Studio 2010 Express Edition.

Upvotes: 6

Views: 5964

Answers (5)

hkBattousai
hkBattousai

Reputation: 10911

The errors are because of trying to write the definition of the template method in the CPP file. In order to reduce the linking time, it is a rule to write the implementation (definition) of the inline and template methods in the header file. The code below is the correct way of declaring and defining a template method.

VectorConvertor.h

class VectorConvertor
{
    public:
        template <class T>
        static void AppendToVector1(        std::vector<T> & VectorToBeAppended,
                                    const   std::vector<T> & VectorToAppend);

        template <class T>
        static void AppendToVector2(        std::vector<T> & VectorToBeAppended,
                                    const   std::vector<T> & VectorToAppend);

        template <class T>
        static void AppendToVector3(        std::vector<T> & VectorToBeAppended,
                                    const   std::vector<T> & VectorToAppend);


}

template <class T>
void VectorConvertor::AppendToVector1(          std::vector<T> & VectorToBeAppended,
                                        const   std::vector<T> & VectorToAppend)
{
    VectorToBeAppended.reserve(VectorToBeAppended.size() + VectorToAppend.size());
    for (std::vector<T>::size_type i=0; i<VectorToAppend.size(); i++)
    {
        VectorToBeAppended.push_back(VectorToAppend[i]);
    }
}

template <class T>
void VectorConvertor::AppendToVector2(          std::vector<T> & VectorToBeAppended,
                                        const   std::vector<T> & VectorToAppend)
{
    VectorToBeAppended.reserve(VectorToBeAppended.size() + VectorToAppend.size());
    for (std::vector<T>::const_iterator cit=VectorToAppend.cbegin(); cit!=VectorToAppend.cend(); ++cit)
    {
        VectorToBeAppended.push_back(*cit);
    }
}

template <class T>
void VectorConvertor::AppendToVector3(          std::vector<T> & VectorToBeAppended,
                                        const   std::vector<T> & VectorToAppend)
{
    VectorToBeAppended.insert(VectorToBeAppended.end(), VectorToAppend.cbegin(), VectorToAppend.cend());
}

VectorConvertor.cpp

// Nothing to write in the CPP file.

And, this is how to use it in the code:

std::vector<uint8_t> InputData, OutputData;
// ...
VectorConvertor::AppendToVector3(OutputData, InputData);

Upvotes: 0

BЈовић
BЈовић

Reputation: 64223

Besides placing the definition of the template function in the header, or including the source file (cpp file), you could explicitly instantiate your function for whichever types you need it.

Upvotes: 0

aschepler
aschepler

Reputation: 72271

Template linking can get tricky. But the simplest solution is usually:

Put all template definitions in header files.

In this case, you should move the contents of VectorConverter.cpp to VectorConverter.h (or possibly #include "VectorConverter.cpp" at the bottom of VectorConverter.h).

Upvotes: 2

Nathan S.
Nathan S.

Reputation: 5388

In C++ you can't separate the definition in a .cpp file when using templates. You need to put the definition in the header file. See:

http://www.parashift.com/c++-faq-lite/templates.html#faq-35.12

Upvotes: 7

Matt K
Matt K

Reputation: 13842

You need to put the body of the function in the header file. See this FAQ.

Upvotes: 5

Related Questions