[SOLVED] C++: template function instantiation does not work with string as return value. Why?
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Just for information. You don't need to do it that way. With templates (in gcc) you can include the code in the header file and then the compiler will work out which templated functions will be required. So the following will give the same results:
Just for information. You don't need to do it that way. With templates (in gcc) you can include the code in the header file and then the compiler will work out which templated functions will be required.
I think you're missing the point. Of course you can include the function definitions in the header file and not have to deal with this problem. But you might have good reasons to want to keep just function declarations in the header file and function definitions in a .cpp file.
TITiAN clearly wanted to do that and knew the basics of how to do that and merely made a couple minor errors in the details. But then started thinking there was something more fundamental wrong with the mechanism, rather than spotting the couple details that were wrong.
When you think of that whole expression just as "string", it all becomes clear.
Right now I'm having issues with a template function that accepts "T const&" as an argument, but before I start another thread, I'll tear out my own hair
Right now I'm having issues with a template function that accepts "T const&" as an argument, but before I start another thread, I'll tear out my own hair
Take yet another look at my main post of this thread. Notice what I said about the compiler's unfortunate behavior when it matches quoted text to a template argument of the form T const&
I hate links to long documents posted alone as apparent answers in complicated threads.
Whose question do you think you're answering? What part of that question do you think you're answering? What part of that long document do you think provides that answer?
The OP in this thread was never confused about the basic questions of why it is easier to have the definition in header rather than cpp files, nor the more advanced question of what you need to do when you really want the definition in a cpp anyway. The OP was only messing up some details within that and already solved even those details.
The link you posted seems to only cover the basics of that, which the OP didn't need and which others in this thread should already understand from what was already in this thread.
The OP (and maybe me as well) are now confused about some of the strange consequences of using T const& as the parameter type in a templated function. Is there something I missed in that document you linked that helps with that question?
The OP (and maybe me as well) are now confused about some of the strange consequences of using T const& as the parameter type in a templated function. Is there something I missed in that document you linked that helps with that question?
give me an example, maybe I can get an answer to you.
give me an example, maybe I can get an answer to you.
I'm not sure I have an example where I don't know the answer. Maybe TITiAN will post one.
I have complicated examples, some of which simplify to the example below and others I'm not sure. When I started being confused by this topic 8 years ago, I would not have understood the behavior of the complicated examples that do simplify to the one below. Once it is that simplified as shown below, the behavior is much easier to understand. But I expect many experienced C++ programmers would be surprised at the output of even this simple program:
size = 5
when going through test2 size = 4
size = 8
when going through test2 size = 8
Why is a double the same size in test1 as in test2, while "text" is 5 bytes in test1 and 4 in test2.
In more complicated cases, I used to make the simple assumption that "test" was a char const* which is 4 bytes (in x86) so that a reference to "text" would be a reference to a char const* which would be a reference to a type that is 4 bytes, just a 1.3 is a double, which is 8 bytes while a reference to 1.3 is a reference to a type that is 8 bytes.
In other words, I thought passing by reference gives you a reference to the type that would have been passed if the same parameter had been passed by value. But that is not generally true.
When writing a very general template that must be prepared to deal with many kinds of input, some of which really ought to be passed by const&, it may be tricky to deal with this extra difference between passing by value and passing by const& (that it is a const& to some other type than would have been passed by value).
You'll get the same difference without templates, it's because one is measuring the size of the literal, the other measuring the size of the pointer:
I know one is measuring the literal and one is measuring the pointer. That wasn't the tricky part. The tricky part was why. Look at how the two templates are declared and called. It is initially confusing that they behave differently.
/tmp/ccS1eD8a.o: In function `main':
main.cpp:(.text+0x11): undefined reference to `void test<char [5]>(char const (&) [5])'
collect2: ld returned 1 exit status
As johnsfine mentioned before, g++ wants me to use this template instantiation for the purpose:
Code:
template void test<char[5]> (char const(&)[5]);
Obviously, it would be ridiculous to make instantiations for all possible sizes.
BTW this works:
Code:
#include <iostream>
using namespace std;
template <typename T>
void test (T const& o)
{
cout << o << endl;
}
int main (int args, char** arg)
{
test("test");
return 0;
}
Last edited by TITiAN; 06-26-2010 at 09:19 AM.
Reason: forgot "const char*" in the first line
I figured something out: If I change this line from main.cpp
Code:
test("test);
into this:
Code:
test((const char*)"test");
it works.
So I guess the compiler can automatically convert char[5] into const char*, but not when it has to deduce that char[5] is const char* as in const char* const&.
I wonder if there has been some confusion about how references work?
As I understand it the reference is established in the declaration and not in the calling of a function. So if you pass a reference of an object to a function that is not expecting a reference then a copy is made. Whereas if in the declaration the function says that it expects a reference then a reference will be used.
The following example first looks at it from a function perspective and then a templated function.
template.h
Code:
#include <string>
#include <iostream>
using std::cout;
class MyClass
{
private:
int number;
public:
MyClass (int num):number(num){cout << "In constructor.\n";}
MyClass (const MyClass& obj):number(obj.number){cout << "In copy constructor.\n";}
friend std::ostream& operator<<(std::ostream& os, const MyClass& obj) {os << obj.number<<std::endl; return os;}
};
template <class T>
void ttest(T const & t);
void test (MyClass obj);
void rtest (MyClass const & obj);
In constructor.
3
3
In copy constructor.
3
3
3
In copy constructor.
3
The two functions test() and rtest() are just normal functions. When test() is called a copy is made. Whenever rtest() is called regardless of whether the object or reference to the object is called no copy is done. The function ttest() is just the rtest() function converted to a template function.
My recommendation would be to have the concepts clear by writing a non-templated function if the creation of the templated version is becoming problematic
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.