LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
LinkBack Search this Thread
Old 06-25-2010, 03:50 AM   #16
graemef
Senior Member
 
Registered: Nov 2005
Location: Hanoi
Distribution: Fedora 13, Ubuntu 10.04
Posts: 2,376

Rep: Reputation: 147Reputation: 147

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:

template.h
Code:
#include <string>
#include <iostream>

template <class T>
void test(T t)
{
	std::cout<<t<<std::endl;
}


template <class T>
std::string str(T t)
{
	std::string ret=std::string(t);
	return ret;
}
main.cpp
Code:
#include "template.h"

int main (int args, char** arg)
{
	test("test");       // char const*
	test(1);            // int
	test(2);            // int
	test(3.2);          // double
	test(str("test"));  // string
}
Note the main is unchanged I have just included it for completeness.

Last edited by graemef; 06-25-2010 at 03:52 AM.
 
0 members found this post helpful.
Old 06-25-2010, 05:12 AM   #17
johnsfine
Senior Member
 
Registered: Dec 2007
Distribution: Centos
Posts: 4,969

Rep: Reputation: 1075Reputation: 1075Reputation: 1075Reputation: 1075Reputation: 1075Reputation: 1075Reputation: 1075Reputation: 1075
Quote:
Originally Posted by graemef View Post
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.
 
Old 06-25-2010, 05:33 AM   #18
TITiAN
Member
 
Registered: Mar 2008
Location: NRW, Germany
Distribution: Debian GNU/Linux with XFCE and packages from "testing"
Posts: 377

Original Poster
Rep: Reputation: 46
One thing that confused me for most of the time was that g++ calls the string type this:
Code:
std::basic_string<char, std::char_traits<char>, std::allocator<char> >
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
 
Old 06-25-2010, 05:55 AM   #19
johnsfine
Senior Member
 
Registered: Dec 2007
Distribution: Centos
Posts: 4,969

Rep: Reputation: 1075Reputation: 1075Reputation: 1075Reputation: 1075Reputation: 1075Reputation: 1075Reputation: 1075Reputation: 1075
Quote:
Originally Posted by TITiAN View Post
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&
 
Old 06-25-2010, 06:55 AM   #20
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: FreeBSD, Debian, Mint, Puppy
Posts: 3,269

Rep: Reputation: 165Reputation: 165
http://www.parashift.com/c++-faq-lit...html#faq-35.12
 
0 members found this post helpful.
Old 06-25-2010, 07:41 AM   #21
johnsfine
Senior Member
 
Registered: Dec 2007
Distribution: Centos
Posts: 4,969

Rep: Reputation: 1075Reputation: 1075Reputation: 1075Reputation: 1075Reputation: 1075Reputation: 1075Reputation: 1075Reputation: 1075
Quote:
Originally Posted by bigearsbilly View Post
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?

Last edited by johnsfine; 06-25-2010 at 07:43 AM.
 
Old 06-25-2010, 08:49 AM   #22
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: FreeBSD, Debian, Mint, Puppy
Posts: 3,269

Rep: Reputation: 165Reputation: 165
well excuse me for not meeting your criteria.

I thought it may help the OP.
It is also a useful resource for C++ problems.

I thought it was fairly relevent myself,
the FAQ says:
Quote:
Why can't I separate the definition of my templates class from its declaration and put it inside a .cpp file?
which is what the OP was attempting.
if you read the FAQ it refers to the next two which give solutions to the problem.
OP:
Quote:
But when the return type is std::string, linker errors occur.
next FAQ:
Quote:
How can I avoid linker errors with my template functions?
one after that....
Quote:
How does the C++ keyword export help with template linker errors?

obviously I am an idiot.
 
Old 06-25-2010, 09:01 AM   #23
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: FreeBSD, Debian, Mint, Puppy
Posts: 3,269

Rep: Reputation: 165Reputation: 165
Quote:
Originally Posted by johnsfine View Post

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.
 
Old 06-25-2010, 10:19 AM   #24
johnsfine
Senior Member
 
Registered: Dec 2007
Distribution: Centos
Posts: 4,969

Rep: Reputation: 1075Reputation: 1075Reputation: 1075Reputation: 1075Reputation: 1075Reputation: 1075Reputation: 1075Reputation: 1075
Quote:
Originally Posted by bigearsbilly View Post
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:

Code:
#include <iostream>

template <class T> void test1(T const& t) {
    std::cout << "size = " << sizeof(t) << std::endl;
}

template <class T> void test2(T t) {
    std::cout << "when going through test2 ";
    test1(t);
}

int main (int args, char** arg) {
    test1("text");
    test2("text");
    test1(1.3);
    test2(1.3);
    return 0;
}
Code:
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).

Last edited by johnsfine; 06-25-2010 at 10:28 AM.
 
Old 06-25-2010, 08:30 PM   #25
graemef
Senior Member
 
Registered: Nov 2005
Location: Hanoi
Distribution: Fedora 13, Ubuntu 10.04
Posts: 2,376

Rep: Reputation: 147Reputation: 147
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:
Code:
#include <iostream>

int main (int args, char** arg)
{
    char * text = "text appears here";
    std::cout << sizeof(text) << std::endl;
    std::cout << sizeof("text appears here") << std::endl;
    return 0;
}
gives the following output:
Code:
4
18
 
Old 06-26-2010, 06:23 AM   #26
johnsfine
Senior Member
 
Registered: Dec 2007
Distribution: Centos
Posts: 4,969

Rep: Reputation: 1075Reputation: 1075Reputation: 1075Reputation: 1075Reputation: 1075Reputation: 1075Reputation: 1075Reputation: 1075
Quote:
Originally Posted by graemef View Post
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.
 
Old 06-26-2010, 09:12 AM   #27
TITiAN
Member
 
Registered: Mar 2008
Location: NRW, Germany
Distribution: Debian GNU/Linux with XFCE and packages from "testing"
Posts: 377

Original Poster
Rep: Reputation: 46
I still don't understand why I can't use "const char* const&" as an argument:
main.cpp
Code:
#include "template.h"

int main (int args, char** arg)
{
	test("test");
	return 0;
}
template.cpp
Code:
#include <iostream>

#include "template.h"

template <class T>
void test(T const& t)
{
	cout<<t<<endl;
}
template void test<const char*> (const char* const&);
template.h
Code:
#include <string>

using namespace std;

template <class T>
void test(T const&);
`g++ *.cpp' returns:
Code:
/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
 
Old 06-26-2010, 09:22 AM   #28
TITiAN
Member
 
Registered: Mar 2008
Location: NRW, Germany
Distribution: Debian GNU/Linux with XFCE and packages from "testing"
Posts: 377

Original Poster
Rep: Reputation: 46
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&.
 
Old 06-26-2010, 09:41 AM   #29
TITiAN
Member
 
Registered: Mar 2008
Location: NRW, Germany
Distribution: Debian GNU/Linux with XFCE and packages from "testing"
Posts: 377

Original Poster
Rep: Reputation: 46
Dear Diary,
Today was a lucky day: I found a solution for the problem the use of the "T const&" template type has.

The working version looks like this:
main.cpp
Code:
#include "template.h"

int main (int args, char** arg)
{
	test("test");
	return 0;
}
template.cpp
Code:
#include <iostream>

#include "template.h"

template <class T>
void test(T const& t)
{
	cout<<t<<endl;
}
void test(char const* t) {test<char const*>(t);}
template.h
Code:
#include <string>

using namespace std;

template <class T>
void test(T const&);

void test(char const*);
That's a practicable solution that even works with the const& statement, I suppose.

The function
Code:
void test(char const* t) {test<char const*>(t);}
splits up the automatic conversions (char[5]->char const* and char const*->char const* const&).

Last edited by TITiAN; 06-26-2010 at 10:07 AM. Reason: thought I had a solution before, but just now I figured out one
 
Old 06-27-2010, 02:03 AM   #30
graemef
Senior Member
 
Registered: Nov 2005
Location: Hanoi
Distribution: Fedora 13, Ubuntu 10.04
Posts: 2,376

Rep: Reputation: 147Reputation: 147
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);
template.cpp
Code:
#include "template.h"

template <class T>
void ttest(T const & t)
{
	std::cout<<t<<std::endl;
}
template void ttest<MyClass>(MyClass const &);

void test(MyClass obj)
{
	std::cout<<obj<<std::endl;
}

void rtest(MyClass const & obj)
{
	std::cout<<obj<<std::endl;
}
main.cpp
Code:
#include "template.h"

int main (int args, char** arg)
{
   const MyClass mc(3);
   ttest(mc);
   rtest(mc);
   test(mc);
   MyClass const & ref = mc;
   ttest(ref);
   rtest(ref);
   test(ref);
}
output
Code:
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
 
  


Reply

Tags
cpp, header, return, split, string, template


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
C++: different instances of a function template unihiekka Programming 3 02-05-2009 01:50 PM
C++ Template For Generic Function - Is This Possible? taylor_venable Programming 6 06-05-2006 08:46 PM
Standard Template Library Reference (std::string) lucky6969b Programming 3 03-15-2006 03:09 PM
can a function return a string? hubabuba Programming 13 03-06-2005 02:51 PM
function prototypes in template class' (c++) qwijibow Programming 4 12-13-2004 09:34 AM


All times are GMT -5. The time now is 10:36 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration