0

I wrote myself a StringHelper in cpp to convert. But it won't compile if I put the sourceode in an external cpp-file (included in the Codeblocks-projectfile) or I don't understand the errors:

HPP:

#ifndef _INPUT_STRINGHELPER_HPP
    #define _INPUT_STRINGHELPER_HPP

    #include <string>
    #include <sstream>
    #include <deque>

    namespace FiveDimension
    {
        void SplitStream(std::stringstream& s, char c, std::deque<std::string>& ret);
        void SplitString(std::string s, char c, std::deque<std::string>& ret);
        template<typename T> T StringToAll(std::string val);
        template<typename T> bool TryStringToAll(std::string val, T &ret);
        template<typename T> std::string AllToString(T val);
    }

#endif

CPP:

#include "StringHelper.hpp"

void FiveDimension::SplitStream(std::stringstream& s, char c, std::deque<std::string>& ret)
{
    std::string line;

    while(std::getline(s, line, c))
        ret.push_back(line);
}
void FiveDimension::SplitString(std::string s, char c, std::deque<std::string>& ret)
{
    std::string line;
    std::stringstream ss(s);

    while(std::getline(ss, line, c))
        ret.push_back(line);
}
template<typename T> T FiveDimension::StringToAll(std::string val)
{
    std::stringstream s(val);
    T ret;
    s >> ret;
    return ret;
}
template<typename T> bool FiveDimension::TryStringToAll(std::string val, T &ret)
{
    std::stringstream s(val);
    return (s >> ret);
}
template<typename T> std::string FiveDimension::AllToString(T val)
{
    std::stringstream s;
    s << val;
    return s.str();
}

I also tried for example:

template<typename T> std::string FiveDimension::AllToString<T>(T val)
{
    std::stringstream s;
    s << val;
    return s.str();
}

but this doesn't even compile this file and make me feel I don't know anything about templates so I came here. I read the answer by Aaron on this topic: "Undefined reference to" template class constructor . After that I understood a lot more. But how can I predefine a function ?

Community
  • 1
  • 1
Joshua Behrens
  • 818
  • 13
  • 23
  • The accepted answer to that question tells you pretty much everything you should need to know. Which part of it is troubling you? – Oliver Charlesworth Jun 05 '12 at 14:29
  • Edit the title of your post because [Stack Overflow is not in need of your SEO skills](http://meta.stackexchange.com/a/130208/142865) – John Dibling Jun 05 '12 at 14:42
  • @OliCharlesworth In the thread-link I posted is everything I had to know, but how do I now preimplement a function - for example AllToString ? – Joshua Behrens Jun 05 '12 at 14:53
  • possible duplicate of [Why should the implementation and the declaration of a template class be in the same header file?](http://stackoverflow.com/questions/3749099/why-should-the-implementation-and-the-declaration-of-a-template-class-be-in-the) – Bo Persson Jun 05 '12 at 15:39

2 Answers2

0

A template isn't actual code, it's the instructions for building the code once all the template parameters are filled in. To do that, the compiler must have the full template definition at the point where the template function is used. You must make the templated code accessible from the header file.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • Thanks for your "help" but all this stuff is written behind the link I wrote within my question. – Joshua Behrens Jun 05 '12 at 14:55
  • @JoshuaBehrens, sorry I didn't see the link - all I saw was a huge wall of code and a misunderstanding of how templates work. – Mark Ransom Jun 05 '12 at 15:10
  • a tl;dr would have been enough ;) But I think I think Forgottn is on the right track, what I want to know. I can't describe it better, because English is not my native language. – Joshua Behrens Jun 05 '12 at 15:18
0

I'll do a brief of the answer, that is in the topic, you've mentioned: There are two ways out of this problem:

  1. Use inlines (I know, that you don't want to, but it's more general and correct way).
  2. Use definitions of the types you'll be using in the .cpp file.

For template classes you should use the following code:

template class your_class_name < typename_to_use >;

Where typename_to_use is something like int, std::string or else. For template functions you should use the following code:

template return_type your_function_name<typename_to_use>(...parameters);

For template member functions you should use the following code:

template return_type your_class_name::your_function_name<typename_to_use>(...parameters);

or

template return_type your_class_name<class_typename_to_use>::your_function_name<function_typename_to_use>(...parameters);

The last case is describing the situation when the template class uses a template function.

Forgottn
  • 563
  • 3
  • 11
  • It helped me a lot how to include this preimplementation but I used this: template bool FiveDimension::TryStringToAll(std::string val, int &ret); in the header and it still throws the undefined reference to FiveDimension::TryStringToAll. – Joshua Behrens Jun 05 '12 at 15:10
  • Try `template bool FiveDimension::TryStringToAll(std::string val, int &ret);`, or maybe (I'm not sure) `template<> bool FiveDimension::TryStringToAll(std::string val, int &ret);` – Forgottn Jun 05 '12 at 15:21