Question C++/Template specialization

On which function does the linker give an error? The specialized function for std::string should only be present in the template.o / template.obj file, and the other source files should have it as an external symbol only, because of the declaration in the header file.

I can imagine that, when the general function is used for the same type in different source files (e.g. a.cpp uses Test::get_value<int> and b.cpp also uses Test::get_value<int>), that the same symbol ends up in different object files.

I don't know how this is handled, but I've never had a problem with this (at least not with GCC). I think the compiler should know when a specialized function is generated locally, and it should not export symbols for these. Alternatively, maybe it does export symbols with a special flag / in a special section, so that the C++ linker can remove all the doubles.
The problem is with the non-specialized function. I don't usually use #ifndef guards for headers, but that's not the problem (yes, I've tested it). The problem is that the linker doesn't remove the double (and it shouldn't. How does it know which is the right version to use?). I'm currently downloading TDM/MinGW to test this, but I don't expect it to be different.

---------- Post added at 06:05 PM ---------- Previous post was at 05:47 PM ----------

Got the problem: I had the specialization implemented in another file, so that (I don't know why), the whole class became global. If I put the specialization in the header, everything is good and there are no name clashes.

I can reestructure the class to avoid those linking errors by moving everything from the cpp file to the header file, but if I use the same class in different files, my executable will become bloated...
 
I tried having two source files which both use testObj.get_value<int>():

test2.cpp:
Code:
#include "template.h"

int use_template();

int use_template()
{
    Test testObj;
    return testObj.get_value<int>();
}

test.cpp:
Code:
#include <iostream>

using namespace std;

#include "template.h"

int use_template();

int main()
{
    Test testObj;
    cout << testObj.get_value<std::string>() << endl;
    cout << testObj.get_value<int>() << endl;
    cout << use_template() << endl;
    cout << testObj.get_value<float>() << endl;

    return 0;
}

And it just works.

I also found a sort of explanation on how it works:
http://www.airs.com/blog/archives/52
 
In the end, this was such a simple issue. The header file is big and ugly but it works the same way <vector> does, and this thread has proven my total lack of understanding of the compilation system and C++. I've wasted a day :dry:.

Gonna go to bed. Tommorow I'll read the article you linked. Thanks for the help!

:zzz:
 
Gonna go to bed. Tommorow I'll read the article you linked. Thanks for the help!
:zzz:

You go to bed early! If you're in Brazil, I think it's about 18:45 now.

Anyway, with this sort of problem, it's either some stupid thing like a typo, or some incredibly difficult to understand C++ compiler/linker issue. Good luck, tomorrow!
 
You go to bed early! If you're in Brazil, I think it's about 18:45 now.

Anyway, with this sort of problem, it's either some stupid thing like a typo, or some incredibly difficult to understand C++ compiler/linker issue. Good luck, tomorrow!
Your definition of early quickly changes with few nights of bad sleep ;).

I've updated my first post with a summary in case someone stumbles this thread.

Anonymous said:
"C++: Hard to learn and built to stay that way."
Bjarne Stroustrup said:
"In C++ it's harder to shoot yourself in the foot, but when you do, you blow off your whole leg."
 
In the end, this was such a simple issue. The header file is big and ugly but it works the same way <vector> does, and this thread has proven my total lack of understanding of the compilation system and C++. I've wasted a day :dry:.

No worries, but you know - a billion of flies can be wrong, but four Pros not :)
 
Summary of what I've learned in this thread:


  • A template class/method/function should be implemented in a header file to be included in every cpp file where it's needed. It can't be implemented in a separate cpp file (as you'd normally do for normal functions and methods), as the compiler need to know for which types it need to generate code for.
  • A template method can't be implemented outside it's class, even if it's within the same header file. Doing this would create duplicate symbols if the same header is included in different cpp files in a way that the linker can't choose which to use, raising an error.
  • NEVER ask questions if you're in need of a good night's sleep :thumbup:.
First lesson: true.
Third lesson: true, unless maybe there's a really urgent need for answers, and you still have some coffee.

Second lesson:
I don't think that is true. See the examples I gave you; they all work for me. If it doesn't work for you, then maybe you should check whether your compiler has any bugs / unsupported features.

What I know about GCC is that, while compiling of C++ code can be done with the gcc command (like C code), you need to call the g++ command to link the object files together. If you use the gcc command for linking, then some C++ features will not work properly. This is probably one of those features.

I think C++ is so hard because of all the features they tried to combine:

  • Backward compatibility with C
  • No compromises when it comes to speed
  • High-level language constructions, like templates and virtual functions
 
I think C++ is so hard because of all the features they tried to combine:

  • Backward compatibility with C
  • No compromises when it comes to speed
  • High-level language constructions, like templates and virtual functions

I think you are right on 2&3, but not on 1... if you look at other C-like programming languages, like Java, Scala or C#, the C syntax heritage is a pretty powerful one. It is maybe a bit like Go... simple rules, but complex interactions of these. Just look at the pre-increment/post-increment rule and its many implications.

The high-level language part is also not too extreme, if you compare it to other more modern languages. It is just maybe OOP on the cheap side. Very powerful abilities for writing programs, but only weak ones for debugging and maintenance. I find it very disappointing that the language feature of "Concepts" got struck from the C++0x standard, if this would have been tamed, it would have been a very powerful tool.
 
Second lesson:
I don't think that is true. See the examples I gave you; they all work for me. If it doesn't work for you, then maybe you should check whether your compiler has any bugs / unsupported features.
Will take a look at that. Strange thing is that I only posted that after testing, because I wasn't really sure it was true.

I'm using VC2008, but GCC is no problem for me (I use Linux, unless it's something Orbiter-related).

I think C++ is so hard because of all the features they tried to combine:

  • Backward compatibility with C
  • No compromises when it comes to speed
  • High-level language constructions, like templates and virtual functions
1&2 are obviously right. 3 is not, as the problem is how the got implemented, and not with the combination itself.

I think you are right on 2&3, but not on 1... if you look at other C-like programming languages, like Java, Scala or C#, the C syntax heritage is a pretty powerful one. It is maybe a bit like Go... simple rules, but complex interactions of these. Just look at the pre-increment/post-increment rule and its many implications.

The high-level language part is also not too extreme, if you compare it to other more modern languages. It is just maybe OOP on the cheap side. Very powerful abilities for writing programs, but only weak ones for debugging and maintenance. I find it very disappointing that the language feature of "Concepts" got struck from the C++0x standard, if this would have been tamed, it would have been a very powerful tool.
It's not a C heritage, but Algol heritage. You've never seen Lisp or Haskell, have you?
 
I think you are right on 2&3, but not on 1... if you look at other C-like programming languages, like Java, Scala or C#, the C syntax heritage is a pretty powerful one. It is maybe a bit like Go... simple rules, but complex interactions of these. Just look at the pre-increment/post-increment rule and its many implications.

There is a difference between "C-inspired" and "C-compatible". C++ tries to be C-compatible. This means, for instance, that C++ has two different pointer types: the old C pointers, and the safer, but less powerful references. If C-compatibility was not required, they could have replaced the C-style pointer with a more powerful reference type.
 
It's not a C heritage, but Algol heritage. You've never seen Lisp or Haskell, have you?

I have seen them both, both are nice for theory, but effectively useless for praxis, since more than a few algorithms with them is impossible, since the reality is not that function oriented. Better some compromise languages there, like Scala or Conjure, which are offering more imperative or object oriented features.

---------- Post added at 08:54 PM ---------- Previous post was at 08:51 PM ----------

There is a difference between "C-inspired" and "C-compatible". C++ tries to be C-compatible. This means, for instance, that C++ has two different pointer types: the old C pointers, and the safer, but less powerful references. If C-compatibility was not required, they could have replaced the C-style pointer with a more powerful reference type.

Why? If you need a high-level data structure pointer, you can use one suitable of the many smart pointer classes (especially shared_ptr is a pretty jack of all trades). References are also doing a great job for argument passing or for simplifying calculations, but as you said, they are not exactly powerful, since they lack the low-level, no-thrills charm of pointers.

But as I said above, pointers are not the end, they are only the beginning.

http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/smart_ptr.htm
 
Last edited:
I have seen them both, both are nice for theory, but effectively useless for praxis, since more than a few algorithms with them is impossible, since the reality is not that function oriented. Better some compromise languages there, like Scala or Conjure, which are offering more imperative or object oriented features.
http://weitz.de/cl-ppcre/: Portable Perl-Compatible Regular Expressions for Common Lisp. I didn't quite understand 'since more than a few algorithms with them is impossible'.

Haskell is function-oriented (which says absolutely nothing about what it can or can't do), but Lisp is a jack-of-all-trades. You can write an imperative, Java-like (i.e., full of superfluous classes) program in Lisp as easy as you can write one that depends only on functions.
 
http://weitz.de/cl-ppcre/: Portable Perl-Compatible Regular Expressions for Common Lisp. I didn't quite understand 'since more than a few algorithms with them is impossible'.

Haskell is function-oriented (which says absolutely nothing about what it can or can't do), but Lisp is a jack-of-all-trades. You can write an imperative, Java-like (i.e., full of superfluous classes) program in Lisp as easy as you can write one that depends only on functions.

Then do it. I know that you can, with insane effort, even write complete applications in assembler, but that doesn't say that assembler is a suitable language for the task. You can also do the shopping run with a Harrier.

I don't want to do larger projects in a function oriented language, not even with something like Scala, because other languages are far more better suited for the task - the function orientation, which is nice for multi-core optimization, can also be reproduced in other languages, with more effort. and that is the problem for current function oriented languages: They are too theoretical for being irreplaceable.

And "full of superfluous classes" is a statement that only shows in my personal opinion, that you are only talking hot air here. Superfluous is a statement that means,you can say that a class is not needed, and that is pretty hard, even for something like Java. Especially it shows that you have yet to understand what object orientation means and why it was invented - because otherwise, you would know that even abstract classes, that produce no useful code on their own, serve an important function (at least, they have more purpose than closures, which is a nice pattern that can be replaced by about one dozen alternatives, unless you are limited to function oriented programming)
 
I know I may sound a fanboy by saying that language X, which is not mainstream (heck, a 'billion of flies can't be wrong'), is better than language Y because of a set Z of characteristics. But heck, with all due respect (and I can't even begin to compare myself to you), you're worse because of the opposite.

'I know that you can, with insane effort, even write complete applications in assembler': Reductio ad absurdum. I know that you're making a parallel here, but it's just wrong to compare the effort of writing an application in an extremely high-level language (more abstract than most mainstream languages today) with the effort of writing the same app in assembly (BTW, assembler is the app that assemble assembly, no pun intended).

'I don't want to do larger projects in a function oriented language', 'and that is the problem for current function oriented languages: They are too theoretical for being irreplaceable': You use your opinion as stated facts. NO feature is irrepleaceable, as long as it's still possible to do something in language Q. Feature are extras, and a language that forces a vision of the world based on them (which is the case of, for example, Java) is, IMO, not needed and even harmful.

'the function orientation, which is nice for multi-core optimization', 'at least, they have more purpose than closures, which is a nice pattern that can be replaced by about one dozen alternatives, unless you are limited to function oriented programming': Those two statements show your complete lack of understanding of functional programming, which may be the base of the complete hatred (as it seems to me) of any language which implements it.

'Especially it shows that you have yet to understand what object orientation means and why it was invented': Yes, I do know most of the things needed to know about OOP. I know what's an abstract class, static class, polyphormism, heritance and the like. I also know when to use it and when to not, but the latter is far more important.

'And "full of superfluous classes" is a statement that only shows in my personal opinion, that you are only talking hot air here.': Superfluous, in the case of Java, because everything needs to be a class, even things that, in the vision of a programmer without it's mind closed on Java, shouldn't, like the entry point. The need of the use of objects give raise to 'placeholder classes', where some other paradigm may be better suited to solve a problem, and OOP masturbation.

To wrap up, and to not make this post longer than it should be (no need for [RANT][/RANT] :P), it seems to me, Urwumpe, with all due respect (and I really mean it), that your mind is closed on 'Design Patters', 'Goto Considered Harmful', 'Java for Entrerprise' and the like. As far as I'm concerned, this isn't a problem as long as you don't use some of their flawed arguments. There are literally hundreds of ways of solving the same problem, and another thousand of ways of representing that solution. Imperative, OOP, C/C++ and Java are just as definite solution as functional, raw binary, Lisp, Haskell and everything else are.

---------- Post added at 07:05 PM ---------- Previous post was at 06:58 PM ----------

Just to add more wood to the fire, take a look at Emacs, which is a simple text editor with a Lisp interpreter. Because it's also a Lisp interpreter, it's considered by many a complete OS, as there are literally millions of apps for it, which do from simple things like adding color to source code, to reading and writing email, to playing games, to browse the internet and to be used as shell (replacing popular shells like bash, csh and zsh).

This wouldn't be possible without it being a Lisp interpreter in the first place. For me at least, that's on the other extreme of being 'theoretical'.
 
Just to add more wood to the fire, take a look at Emacs, which is a simple text editor with a Lisp interpreter. Because it's also a Lisp interpreter, it's considered by many a complete OS...

Look, Shall I really answer something now, or can I just leave the thread and go laughing? :rofl:
 
Look, Shall I really answer something now, or can I just leave the thread and go laughing? :rofl:
:blink:

Do as you please, but you only read that part? Dissapointing, as I thought I'd get a real answer.
 
:blink:
Do as you please, but you only read that part? Dissapointing, as I thought I'd get a real answer.

I had read it all, but really, it was summarizing your competence pretty well, and I thought it is now a good point to stop this discussion before you get more chances to loose your face here. I am evil, but I am not mean.
 
I had read it all, but really, it was summarizing your competence pretty well, and I thought it is now a good point to stop this discussion before you get more chances to loose your face here. I am evil, but I am not mean.
No, no, please do answer. I prefer to 'loose my face' in a real answer than trying to guess what you're talking about.

Also, I'm trying to keep it civil. I do know my ignorance is limitless, but it's impossible to expand my knowledge without answers, arguments and couter-arguments.
 
Fine, you wanted it, you'll get it (But warning, I am deeply in Party Law today, so don't be shocked when I start to sing my clubs anthem while typing this):

'I know that you can, with insane effort, even write complete applications in assembler': Reductio ad absurdum. I know that you're making a parallel here, but it's just wrong to compare the effort of writing an application in an extremely high-level language (more abstract than most mainstream languages today) with the effort of writing the same app in assembly (BTW, assembler is the app that assemble assembly, no pun intended).

Oh, my fault...in German, the language is assembler as well. Must do this error often.

It is more than that, it is a matter of : The right language for the right task. You can't write a Real-time system in Visual Basic, so why try it? And how to develop a full application for a complex task in a function oriented language, when this task negates nearly all advantages of functional programming?

'I don't want to do larger projects in a function oriented language', 'and that is the problem for current function oriented languages: They are too theoretical for being irreplaceable': You use your opinion as stated facts. NO feature is irrepleaceable, as long as it's still possible to do something in language Q. Feature are extras, and a language that forces a vision of the world based on them (which is the case of, for example, Java) is, IMO, not needed and even harmful.

No, that is not just an opinion, see above. And Java is just another object-oriented language. Same kind of dogma as functional programming or imperative programming, not worse, not better. But still, you have abilities in each dogma, that makes them suited better or worse for a special task. Just try to model events in a purely functional task, where imperative languages have better reactions.

'the function orientation, which is nice for multi-core optimization', 'at least, they have more purpose than closures, which is a nice pattern that can be replaced by about one dozen alternatives, unless you are limited to function oriented programming': Those two statements show your complete lack of understanding of functional programming, which may be the base of the complete hatred (as it seems to me) of any language which implements it.

Don't assume, because you make an ass out of U and me. I had likely seen more functional programming in my life than you did, and if I would really hate it, I wouldn't see great uses for it, especially inside applications like Orbiter, where control loop processing and autopilots are crying for function orientation.

And please: Show me one semantic feature of closures, that can't be implemented in object-oriented or imperative languages without using a closure.

'Especially it shows that you have yet to understand what object orientation means and why it was invented': Yes, I do know most of the things needed to know about OOP. I know what's an abstract class, static class, polyphormism, heritance and the like. I also know when to use it and when to not, but the latter is far more important.

'And "full of superfluous classes" is a statement that only shows in my personal opinion, that you are only talking hot air here.': Superfluous, in the case of Java, because everything needs to be a class, even things that, in the vision of a programmer without it's mind closed on Java, shouldn't, like the entry point. The need of the use of objects give raise to 'placeholder classes', where some other paradigm may be better suited to solve a problem, and OOP masturbation.

So, you think that structuring programs by inheritance, having encapsulation of data or have code representations of formal software design tools is superfluous?

Also, "OOP masturbation" is a good reason more to doubt your experience with OOP. I don't need harsh words against functional programming, because I can talk about it without hate speak. Programming languages are just tools, and I have no sexual fetish for my tools, maybe you should ask yourself how much professionalism you have. I know that I can develop the same pseudoreligious zeal against managed code, but then, I at least remember which brainless coding makes me hate people who think they can let their programming language do the thinking for them.

To wrap up, and to not make this post longer than it should be (no need for [RANT][/RANT] :P), it seems to me, Urwumpe, with all due respect (and I really mean it), that your mind is closed on 'Design Patters', 'Goto Considered Harmful', 'Java for Entrerprise' and the like. As far as I'm concerned, this isn't a problem as long as you don't use some of their flawed arguments. There are literally hundreds of ways of solving the same problem, and another thousand of ways of representing that solution. Imperative, OOP, C/C++ and Java are just as definite solution as functional, raw binary, Lisp, Haskell and everything else are.

You have forgotten to mention my Djikstra shrine. And of course, I should be known for burning Microsoft Press books.

And yes, I really love "Design Patterns". I experienced its power at work and learned quickly to appreciate the approach of having meta-code snippets additionally to the usual heap of code examples. Unless you can show me now a rational reason why it is bad, and which concept can replace such an useful architectural tool, I would happily try it.

Now...in the final analysis: Can you tell me any rational argument in your post? You are only ranting on the emotional level, really like a fan boy. Emacs is good, MS word (which is more powerful on the software development level and has much more "Apps" than Emacs) is bad. When the hype praises Haskell, Haskell is great. When people realize, that, just like with Lisp, it doesn't leave its theoretical niece and remains a toy for fans, it will be forgotten, just like many other hyped programming languages in the past. I remember how somebody said that Modula-2 will be the new standard and how Oberon will be the new standard when Object-Orientation came along.

The problem with hypes is, that coding according to hypes does not bring software. It means selecting a hammer for sawing wood, because its hammertime. Call me cynical, but that is the way it is. In the beginning, when you are young and unexperienced you are enthusiastic about knowing something so esoteric like Brain****, that you forget how useless it is. After many failures, you'll find out that the oldest languages are still around. Ada is not dead yet. Even Fortran is still around. C++ will likely survive D. Java has been talked dead every second year, only to be celebrated the next year. Javascript was hated as security hole and battlefield of browser incompatibilities, now it is standardized and replaces many other hyped proprietary browser extensions for dynamic websites.

And when you are really veteran in the IT business, you will know why it is so. Real programmers are deeply conservative in their work. You have many hackers and free-time coders, who claim the greatest art of their work. But the real mastery comes from silent, conservative, hardworking coders, who sit in the back rows of the xxC3, don't brag about every multi-dimensional recursion, drink aromatic coffee with a saucer under their cups, wear (often black) shirts and ties, have often bald heads instead of thinkgeek shirts, and concentrate in irish pubs at night, instead of the darknet. Most of the real coders of the world think Haskell is a whiskey brewery.

---------- Post added at 12:52 AM ---------- Previous post was at 12:17 AM ----------

BTW, if you really want to do proper OOP masturbation, the code will look like that:

Code:
#include <iostream>
#include <functional>

using namespace std;

template<class T> struct sum : public binary_function<T, T, T> {
  T operator() (const T& a, const T& b) const {
        T result =  a + b;
         cout << "The result is " << result << "." << endl;
         return result;
    };
};

main() {
    sum s;
    s(1,1);
}
At least for replicating the OOP masturbation example in proper C++ code.

Not only is this one absolutely by the current standards of the programming language. It is also still perfectly useless. No sane C++ programmer would write such code. It is still using the Harrier for the weekend shopping. Why should you? The OOP masturbation article is a plain flat insult against OOP, with exaggerated examples for showing how beautiful functional programming can be compared to a completely flawed interpretation of OOP. Now, that was too easy.

How would a octtree look like in a functional language? Not that it would be a simple task in OOP. But that is not the question. The question is: How long does it take in functional programming, to get the solution, implement it and read it again, if you have no idea on what it is? In OOP, it is pretty simple, even if you would use maximal optimizations and turn it into an array of nodes.

And how would a cheap RTS look like in functional programming? Can you do that without catching yourself imitating OOP by having lists of functions for each entity?

The proper C++ answer BTW for just this example, would be:
Code:
#include <iostream>

inline void sum(int a, int b) {
   std::cout << "The result is " << (a+b) << "." << std::endl;
}

main() {
   sum(1,1);
}

Why use a harrier for the weekend purchases?

Such function objects make sense when you want to do such operations on containers, by using algorithms. when the direct object orientated solution would become unreadable, which can happen pretty easily.

The OOP solution should btw be exactly the same object file as the pure functional solution in C++. If I would remove the "inline" in the second version, the second version could even be slightly slower, since the single function call might not be optimized away.
 
Last edited:
Back
Top