How to use a template function in a source file

closed account (jvqpDjzh)
Is it possible to access to a template function (which is implemented in a .h file) from the source file where all other non-template functions are implemented? I have tried, and it seems we can't, this is because the compiler compiles first the source file and doesn't know where the template function is. But my real question is, is there a way to do it anyway?
Thank you!
1
2
3
4
5
6
7
#include <algorithm>
#include <iostream>

int main() {
  std::cout << std::max( 42, 7 ) << '\n';
  return 0;
}

Guess what? The std::max is a template function and it just got called from non-template main(). Successfully.
closed account (jvqpDjzh)
You didn't understand. I am talking about a class with template functions in the header file and the non-templates functions in the source file. What I want is call the template functions from the non-templated functions in the source file, but I can't, it seems.
I am talking about a class with template functions in the header file and the non-templates functions in the source file.
You cannot have non-templated member functions for templated class.
What your code is? How do you call those functions?
Last edited on
closed account (jvqpDjzh)
It's not a template class! It's a non-template class with 3 template functions and the others are NOT template functions and are implemented in the SOURCE file. I would like to use my TEMPLATE functions, which are defined in the HEADER file, inside the NON-TEMPLATE functions defined in the SOURCE file!! My class is NOT a template.
You can. If you cannot that means that you did something wrong. Show stripped down files with minimal amount of code which reproduce your error.
closed account (jvqpDjzh)
I would like to redefine the operator+ to have the possibility to sum a string and a number, that first is converted to a string using my header file defined template function of my non template class:
1
2
3
4
5
6
7
//In the .cpp//this is a friend function
String operator+(const String& str, int num)
{
    String aux(str.ptr);
    aux.Append(ToCString(num));
    return aux;
}

1
2
3
4
5
6
7
8
9
//In the .h file where all my class is declared and there the template 
//functions are defined
    template <typename N>
    const char* ToCString(N number)
    {
        std::ostringstream oss;
        oss << number;
        return oss.str().c_str();
    }


ERROR: ToCString() not declared.
Last edited on
Did you include your .h file with templated function?

You have numerous problems in your templated function:
1) oss is a temporary and will be destroyed after function end, invalidatyng everything related to it.
2) oss.str().c_str(); is never legal and always return a dangling pointer.
The copy of the underlying string returned by str is a temporary object that will be destructed at the end of the expression, so directly calling c_str() on the result of str() results in a dangling pointer.
You didn't understand.

You did not mention "class" or "member". We are not psychics, are we?

temp2.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef TEMP2_H
#define TEMP2_H

#include <iostream>

struct Temp
{
  void bar () const;

  template <typename T>
  void bar ( const T & val ) const
    {
      std::cout << val << '\n';
    }
};

#endif 

temp2.cpp
1
2
3
4
5
6
7
8
#include <iostream>
#include "temp2.h"

void Temp::bar () const
{
  std::cout << "Hello ";
  bar( 7.0 );
}

temp1.cpp
1
2
3
4
5
6
7
8
9
#include "temp2.h"

int main()
{
  Temp foo;
  foo.bar();
  foo.bar( 42 );
  return 0;
}


$ g++ -Wall -Wextra -pedantic -o temp1 temp1.cpp temp2.cpp 
$ ./temp1 
Hello 7
42
$

No errors. No warnings. Output as expected.
$ nm -C temp1 | grep bar
000000000040097e t global constructors keyed to _ZNK4Temp3barEv
0000000000400900 T Temp::bar() const
0000000000400994 W void Temp::bar<double>(double const&) const
00000000004008ce W void Temp::bar<int>(int const&) const

Last edited on
closed account (jvqpDjzh)
Did you include your .h file with templated function?
Yes, I included the "String.h" file, where all my class is declared, etc.

2) oss.str().c_str(); is never legal and always return a dangling pointer.
The copy of the underlying string returned by str is a temporary object that will be destructed at the end of the expression, so directly calling c_str() on the result of str() results in a dangling pointer.
In fact I was not sure about that, but this is not my problem. First I had this:
1
2
3
std::string stdStr = oss.str()
const char* chrPtr = stdStr.c_str();
return chrPtr;
Also this returns a danglinnnngggggg pointer?
Also this returns a danglinnnngggggg pointer?
Yes. Because stdStr is destroyed too after function end. Ypu fixed problem (2) but (1) is still here. You need to use dynamic allocation to make c-string to persist.

Yes, I included the "String.h" file, where all my class is declared
But what about your ToCString() function? Where is it? In what file? What includes it?
Last edited on
Also this returns a danglinnnngggggg pointer?

Yes. chrPtr refers to internals of stdStr. stdStr is a local variable that vanishes at the end of function scope.
closed account (jvqpDjzh)

@zwilu wrote:
It's not a template class! It's a non-template class with 3 template functions and the others are NOT template functions and are implemented in the SOURCE file. I would like to use my TEMPLATE functions, which are defined in the HEADER file, inside the NON-TEMPLATE functions defined in the SOURCE file!! My class is NOT a template.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*String.h*/
class String
{
pubilc:
//declaration of methods
//declaration of other good things
//Finally my template function
    template <typename N>
    const char* ToCString(N number)
    {
        std::ostringstream oss;
        oss << number;
        char* newPtr = new char[oss.str().size() + 1];
        strcpy(newPtr, oss.str().c_str());
        return newPtr;
    }
//other 2 template functions
private:
//cheating
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*String.cpp*/
#include <AMAZON/BOOKS/PAGES/LINES/WORDS/ETC>
//finally my String.h
#include "String.h"

//cheating...

//not cheating
String operator+(const String& str, int num)
{
String aux(str.CString());
//EDIT:
const char* other = ToCString(num);//FAIL
aux.Append(other);
delete [] other;
return aux;
}
//?

//cheating again
}

Last edited on
So your function is a member of class. That means you cannot call it as a freestanding one.

Now it is a generic member. That means you should call it on instance of class: aux.ToCString(5)
You can make it static. After that you should call it on class itself: String::ToCString(5)
Or you can move it outside of your class making it generic function: ToCString(5)
Last edited on
closed account (jvqpDjzh)
So your function is a member of class. That means you cannot call it as a freestanding one
@zwilu wrote:
You didn't understand. I am talking about a class with template functions in the header file and the non-templates functions in the source file. What I want is call the template functions from the non-templated functions in the source file, but I can't, it seems.


That means you should call it on instance of class: aux.ToCString(5)
EXACTLY, THANK YOU! :)

You can make it static. Agter that you should call it on class itself: String::ToCString(5)
Shouldn't the static functions be implemented outside the class declaration?

Or you can move it outside of your class making it generic function: ToCString(5)
Yes, but I would like that this functions is part of the class ;)

Thank you anyway, always helpful!!!!!

EDIT: here's the result:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main()
{
    using wu::String;

    for(int i=0; i<100; i++)
    {
        String str(". Object");
        str = i + str ;//or str = str + i;
        std::cout << "str = "<<str << '\n';
        std::cout << "len = "<<str.Length()<<"\n\n";
    }
    std::cin.get();
    return 0;
}
Last edited on
Shouldn't the static functions be implemented outside the class declaration?
Not nessesary.
But if you want, you can implement it outside of class, but still in same header.

Actually it would be better to make this function static as it does not relies on any fields of instance. That way you can call it even without String instance.
closed account (jvqpDjzh)
But if you want, you can implement it outside of class, but still in same header.
I have thougth about that possibility, but was not sure ;)

Actually it would be better to make this function static as it does not relies on any fields of instance. That way you can call it even without String instance.
Yeah, that's fine! ;)

Last edited on
Topic archived. No new replies allowed.