Jump to content

  • Log In with Google      Sign In   
  • Create Account

what is a template from c++ intent?


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
11 replies to this topic

#1 JohnnyCode   Members   -  Reputation: 329

Like
0Likes
Like

Posted 11 August 2014 - 04:59 PM

I wonder what is a template issued compiler object, is it one of the two following alternatives- and if yes- could you elaborate on anything of the one of the definitions alternatives it misses?

 

A template type of a variable in c++ compiling protocol is :

 

1 alternative : a variable of any type without any compiler ability to check validity of instructions with it?

 

2 alternative : a type of objects that share certain properties and the writer of code wishes to implement unified commands over them without need to derive them from common ancesting object in a strongly types language?

 

or both of them are totaly wrong?



Sponsor:

#2 jwezorek   Crossbones+   -  Reputation: 1986

Like
1Likes
Like

Posted 11 August 2014 - 05:19 PM

Neither is really correct but 2 is closer to correct; 1 sounds more like a C-style macro.

 

Basically you can think of templates as type-safe macros. This is not altogether accurate but is a good first approximation.

 

In other words both macros and templates cause code to get generated. The compiler will do some work for you filling in what you mean. However, in the case macros the way that the preprocessor does this code generation is completely braindead: it doesn't know anything about the types involved it just pastes the arguments into the macro and if what comes out is garbage then so be it.

 

In the case of templates the compiler is checking types while it is doing the code generation.


Edited by jwezorek, 11 August 2014 - 05:20 PM.


#3 JohnnyCode   Members   -  Reputation: 329

Like
-1Likes
Like

Posted 11 August 2014 - 05:35 PM

but macro is just a missplaced continuing code with ability to replace in many places. Template is not. Wtf is template sad.png I am lost never needed to use it, never wished to use it, but I have been in an enviroment where it was a principle to get used. Isn't it just dangerous? As you said, the second alternative is quite close, so it allows one to implement instructions upon objects that do not share ancestors, are being of different types with certain matches, but share possible instructions validity in manner of members. But tamplates for me are such a thin ice.

 

Never ever I have used it actualy. What is it intended exactly for? The second alternative is the only best stuff I could come up with, but it opens missinterpretation that compiler cannot catch, making one's issues more difficult?


Edited by JohnnyCode, 13 August 2014 - 09:31 AM.


#4 SeanMiddleditch   Members   -  Reputation: 7261

Like
2Likes
Like

Posted 11 August 2014 - 06:16 PM

I am lost never needed to use it, never wished to use it, but I have been in an enviroment where it was a principle to get used. Isn't it just dangerous?


Search for "generic programming." They're super useful, by far the most important missing feature from any language that lacks them (C, Go, etc.).

The easy example in C++ is a std::vector or std::unique_ptr. It would totally suck to have to reimplement those over and over and over again for every type.

so it allows one to implement instructions upon objects that do not share ancestors


That is not a bad thing. Needing ancestor types to do things is _bad_, not good.

That said, C++17 (or around then) will have this thing called Concepts which are a way of constraining templates to only works on types that conform to a specific contract (without being forced to add ancestor types).

#5 frob   Moderators   -  Reputation: 22787

Like
7Likes
Like

Posted 11 August 2014 - 07:01 PM

A template is not a variable of any kind. It is not a macro.


I like to think of them as cookie cutters. A cookie cutter defines the shape of the cookie, and you can swap it out with sugar cookie dough, chocolate chip dough, peanut butter dough, oatmeal cookie dough, and any other flavor even if the person who made the cookie cutter hadn't thought about that flavor.

Similarly, templates are not classes by themselves. They are tools the compiler can adjust and manipulate to create code. The compiler can substitute any kind of typename it wants, even typenames that you did not plan on as the template author.

The compiler uses a template to generate code. You provide the typenames or values that are missing, and the compiler will generate a class or function or other content that uses what you provided to create source code for the class. Then it will compile that source code.

Check out my book, Game Development with Unity, aimed at beginners who want to build fun games fast.

Also check out my personal website at bryanwagstaff.com, where I write about assorted stuff.


#6 JohnnyCode   Members   -  Reputation: 329

Like
-7Likes
Like

Posted 11 August 2014 - 08:07 PM

I was too expressive, sorry.


Edited by JohnnyCode, 12 August 2014 - 10:43 AM.


#7 ChaosEngine   Crossbones+   -  Reputation: 2506

Like
7Likes
Like

Posted 11 August 2014 - 08:27 PM

 

std::vector or std::unique_ptr

standard vectors just poses pointers. Right?  Nothing further and they do not mess with a template stuff.
 

In the case of templates the compiler is checking types while it is doing the code generation.

It realy does not, and if it does..... nope, c++ cannot turn to a hell of a brain language can it?
 
Frob, did you ever fall for tamplate usage, or sticked to conforming compiler runtime code? You sure did Frob. Template= utopia!!! IT DOES

 

None of what you have said makes any sense.
 
At a basic level it's not rocket science.
Let's say you have a simple function

int Add(int a, int b) { return a + b; }

Now in non template C++ if you wanted to use that function to add floats or doubles, you'd need to write

float Add(float a, float b) { return a + b; }
double Add(double a, double b) { return a + b; }

ugh... repetition.

With a template you'd write

template <typename T>
T Add(T a, T b) { return a + b; }

when you want to use it, you would write

int x = Add<int>(1, 2);
double x = Add<double>(1.0, 2.0);

and the compiler would generate two functions for you.

int Add_int(int a, int b) { return a + b; }
double Add_double(double a, double b) { return a + b; }

These functions are only generated when you use them.

But let's say you had a class Bar

class Bar
{
};

if you tried to use your Add function with a Bar, the compiler would first generate a new add function

Bar Add_Bar(Bar a, Bar b) { return a + b; }

and then it would issue a compiler error (probably "no operator + found that accepts Bar and Bar")

On the other hand, if you tried to use an std::string with Add

std::string x = Add<std::string>("Hello, ", "World!");

// generated code
// std::string Add_string(std::string a, std::string b) { return a + b; }

this would work fine because std::string defines a + operator.

Now this is a very simple explanation, and leaves out all kinds of complexities like argument matching, SFINAE, specialisation, etc, but that's the basics of it.


if you think programming is like sex, you probably haven't done much of either.-------------- - capn_midnight

#8 Bacterius   Crossbones+   -  Reputation: 9304

Like
0Likes
Like

Posted 11 August 2014 - 09:05 PM


Frob, did you ever fall for tamplate usage, or sticked to conforming compiler runtime code? You sure did Frob. Template= utopia!!! IT DOES

 

You.. do realize that templates are part of the language, right?


The slowsort algorithm is a perfect illustration of the multiply and surrender paradigm, which is perhaps the single most important paradigm in the development of reluctant algorithms. The basic multiply and surrender strategy consists in replacing the problem at hand by two or more subproblems, each slightly simpler than the original, and continue multiplying subproblems and subsubproblems recursively in this fashion as long as possible. At some point the subproblems will all become so simple that their solution can no longer be postponed, and we will have to surrender. Experience shows that, in most cases, by the time this point is reached the total work will be substantially higher than what could have been wasted by a more direct approach.

 

- Pessimal Algorithms and Simplexity Analysis


#9 Ectara   Crossbones+   -  Reputation: 3065

Like
0Likes
Like

Posted 11 August 2014 - 09:07 PM


standard vectors just poses pointers. Right? Nothing further and they do not mess with a template stuff.

Examine your compiler's included headers, and Ctrl+F/grep for "template". A five minute examination would have dispelled your counter-argument.

 

Another good use of generic programming is extensibility. Code that is templated can be used later in a way that the original coder had yet to conceive by substituting new types and values in place of the template parameters.



#10 SeanMiddleditch   Members   -  Reputation: 7261

Like
5Likes
Like

Posted 11 August 2014 - 11:32 PM

Last post on this topic, since I'm not sure this is going anywhere:
 

standard vectors just poses pointers. Right?  Nothing further and they do not mess with a template stuff.


std::vector _is_ a template. That's why you use it like:
 
std::vector<int> foo;
The `<int>` bit is a clear sign that you're instantiating the `std::vector` class template over the `int` type parameter.
 

It realy does not, and if it does..... nope, c++ cannot turn to a hell of a brain language can it?


I'm not entirely sure I'm comprehending your objection, here.

The compiler works in various stages. After preprocessing, there's lexing, parsing, semantic analysis, IR generation, high-level optimization, IR lowering, low-level options, and finally actual machine code generation. Most of the work of verifying templates and instantiating them happen entirely in the earlier stages, though C++ requires some "fuzzines" between the classic stages due to some of its semantic oddities.

You can totally write templates that are constrained today using meta-programming techniques, particular SFINAE. Consider:
 
template <typename T>
auto lerp(float a, T lhs, T rhs) -> decltype(a * lhs + (1 - a) * rhs)
{
  return a * lhs + (1 - a) * rhs;
}
That function will thanks to SFINAE refuse to even instantiate for a type T that does not support operator +. If you try to call lerp on something like a pointer, you'll get a compiler error up front telling you that such operations are not supported. Trying to call it with T=void* for instance, Clang says:
 
10 : error: no matching function for call to 'lerp'
void* c = lerp(1.0f, a, b);
          ^~~~
2 : note: candidate template ignored: substitution failure [with T = void *]: invalid operands to binary expression ('float' and 'void *')
auto lerp(float a, T lhs, T rhs) -> decltype(a * lhs + (1 - a) * rhs)
                                             ^ ~
1 error generated.
Boost has a library library for Concept Checking that generalizes this support.

You can use std::enable_if, std::is_integral, and various other facilities and type traits (all templates!) instead of or in addition to decltype.

Once the Concepts TS is out (around C++17) you can also write the much simpler:
 
template <Arithmetic T>
T lerp(float a, T lhs, T rhs)
{
  return a * lhs + (1 - a) * rhs;
}
Note the `Arithmetic` which is a constraint, meaning that `T` must conform to the given constraint and not just be any generic type.

#11 JohnnyCode   Members   -  Reputation: 329

Like
0Likes
Like

Posted 12 August 2014 - 10:48 AM

 

std::vector _is_ a template. That's why you use it like:
 
std::vector<int> foo;The `<int>` bit is a clear sign that you're instantiating the `std::vector` class template over the `int` type parameter.

 

Yes, you are right, I have never noticed std::vector can interleave objects, not only pointers. I avoided std:: lib always and its vectors.

 

I have coded a pooled memory manager. And I wonder whaether I should do it with a template or with just sizeof operator as I currently have. My point is wheather the template - if not needed- does have a runtime performance impact, or no runtime impact at all.



#12 frob   Moderators   -  Reputation: 22787

Like
5Likes
Like

Posted 12 August 2014 - 12:34 PM

 

Yes, you are right, I have never noticed std::vector can interleave objects, not only pointers. I avoided std:: lib always and its vectors.

 

I have coded a pooled memory manager. And I wonder whaether I should do it with a template or with just sizeof operator as I currently have. My point is wheather the template - if not needed- does have a runtime performance impact, or no runtime impact at all.

 

 

No, there is no additional cost to templates. 

 

In fact the opposite is frequently true.

 

Template functions are typically defined in headers and the compiler nearly always places them in line, eliminating the function overhead. Usually the compiler is then able to further optimize the code to eliminate load/store patterns, move invariants from loops, or otherwise speed things up. Many of those deeply nested template functions can be eliminated when layer after layer is removed through inline optimizations, very often reducing what would be very slow in debug builds to a very simple set of release build code. As an example, some of the built in containers will go through ten or more indirections with assorted tests in debug mode, but in release mode is optimized away completely resulting in just a single direct memory addressing. Algorithm libraries can sometimes suck in large chunks of raw code resulting on many optimization opportunities.

 

Lambda functions similarly offer an optimization opportunity to the compiler. In the worst case it devolves to a function call, but in the best case everything in the function can be elided or inlined. 

 

Those are just two of many examples of how the C++ compilation model can be leveraged to produce even faster, more efficient code. Of course there is a cost to be paid when it comes to compilation. The cost to pull in all those headers, to inline everything, to evaluate hundreds or even of thousands of potential template substitutions is one of the reasons people dislike the language -- all these tasks increase build times. But the end result is an executable that is heavily optimized and CAN BE extremely difficult to beat in terms of performance.

 

There are exactly two C++ features that have a performance cost beyond their direct usage. Those two features are C++ exceptions and RTTI.  All commercial games I have worked on or studied have disabled both of these features. Both of these were heavily debated and nearly removed from the original C++ standard and their use remains a contentious issue to this day. Everything else you can use and feel comfortable knowing that you are using a library that is well defined, debugged, and fast.

 

There are some good reasons to use alternatives to the standard C++ libraries. It is not because of a fear of templates, but because the functionality the standard library offers can be improved on in some measurable way. One oft-cited article in the C++ standard working group is the fairly old writeup of EA's Standard Template Library. It evaluates several things in the 2003 standard that had somewhat better solutions, along with metrics about why the alternative form (which also relied heavily on templates) produced somewhat better results on a range of platforms. Note that those who wrote it did not fear the standard libraries and the language functionality. Instead they embraced it and identified ways to make the system even better by leveraging templates and other features in slightly different ways. Then they ran side-by-side comparisons, improving it further. I liked how in the timing comparisons they also call out the few cases where the library is less performant than the system's library, and how they are usually offset by dramatic performance improvements in other areas.

 

 

As for your not noticing the templates, even in the original 1998 C++ standard the processing of templates and libraries using them represented about 2/3 of the language standard. If you actually learn C++ (instead of learning book about C++) then templates are impossible to miss.

 

If you don't use templates in your code, you are not using C++.  Instead you are likely using "C with classes".


Check out my book, Game Development with Unity, aimed at beginners who want to build fun games fast.

Also check out my personal website at bryanwagstaff.com, where I write about assorted stuff.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS