Container questions

Pages: 123
There is also a free online C++ resource that is great for learning the language, Learn C++:

https://www.learncpp.com/
Thanks George. I hear you about the books, but Sam's is what got me into C++ and remains my first love. But I also wish I knew about the other books before starting this venture.

I bought yet another book and so now I have 4 of them and I will devour them in due time. I had started taking notes and sample programs from Sam's and so now I just want to finish it off for consistencey and add notes from the other books on top of it.

I knew there were tons of libraries and an infinite amount of formulas and methods to performing tasks, but even with the base language it never seems to end and new things constantly pop up for me.

How did you feel when you first read your first C++ book and then news just keeps on trickling in with what seemingly feels like no end in site?
Honestly, what I read said that the VFT is created during compile time and that is EXACTLY how it knows which function to call during run time and that it leaves NO ambiguity.

That is correct. It uses the VFT to look up which function to call at runtime.

But to be able to inline the function call it needs to know which function to call at compile time.

Because if Base was sent as pass by value, pointer, or reference, it will call base methods. If derived was passed as base ref or base pointer, then it calls derived overriding method.

Correct

So what you are telling me is that the compiler doesn't like to look too deeply at the VFT when it is trying to inline?

If the compiler knows the type of the objects and it's always the same type then there is no problem with inlining.

The way inlining works is essentially that you replace the function call with the content of the function itself. How do you do that if the function call expression can invoke different functions depending on what's happening at runtime?

Disregard what the compiler does for one second with inlining, if you as a programmer just looked at the items to be inlined and the VFT during compile time, do you have all the info to figure out if it can be inlined yourself and its just that the compiler has the info but might not want to do it?

I think it should be at least theoretically possible to analyse the code to figure out whether or not inlining is possible but in practice it depends heavily on the compiler and the compiler settings.

Inlining can easily increase the code size which is a big reason why it's not always done even if possible. GCC will inline much more aggressively when using the -O3 compiler flag which often leads to larger executable file compared to -O2.

If the function is not defined in the same translation unit then inlining is generally not possible unless link time optimization (LTO) is enabled.

A) "set" is a class that is templatized.

The official term is "class template".

In other words, std::set not a class. It's a template for generating classes.

You can't simply write "set s2{ 2,5,1,3,2,1,4 };" because it needs the type of template. So what can be said about "set<int>" in here?

As seeplus mentioned, what happens here is that the template arguments are deduced.

The type of s2 is still std::set<int>. This is the same type as std::set<int, std::less<int>, std::allocator<int>>.

Is it fair to call it a type here or do we call it a class

std::set<int> is a class. It's also a type because classes are types.

B) MyClass classObj;
"MyClass" here is a class, but it can also be considered a type, because classes are custom types.

Correct.

(SortDescend<int>) This sends in a type, which is REALLY a struct that is templatized for int type.

Template arguments are passed inside < and >. This is where you might find SortDescend<int>.

Function/constructor arguments are passed inside ( and ). You won't find SortDescend<int> there. You might find SortDescend<int>() but then it's no longer a type but an object.


D)vector<int>::iterator iter;
When I first saw this I thought the left of :: was the class

It is.

and that it called method iterator that then somehow returned an object.

std::vector<int>::iterator is a type.

You can define classes and other types inside a class. You can also define static member variables and static member functions. You don't need an object of the class to use those.
Last edited on
I've been self-teaching myself since before C++98 was the standard. I knew from the start there was no end in sight for learning to better myself. Even if the language was static, never to be improved.

4 books? Heh, try having 4 shelves of programming books plus several stacks of books on the floor, with more than a few eBooks. From C/C++ to WinAPI to specialty books on game programming, DirectX, COM/COM+, MFC, HTML and Java. Lately I've been buying books on specific aspects of C++: move semantics, how to use const, concepts, lambdas, concurrency, the stdlib and how to deal with legacy code. Somewhere in the neighborhood of over 60 books.

That book on legacy code is IMO an essential book 'cuz every resource you learn from deals in legacy code in one form or another. The Beginning C++20 has at least one very glaring example, the section on using std::format. When the book was written and published the only way to catch formatting errors was at run-time with a try/catch block. There was a language standard revision for how C++ deals with format errors and now any formatting errors are caught at compile-time. If only the error message was not so voluminous.

Get over your puppy love for Sams books, to be blunt they are IMO not worth the effort. They are in many ways superficial and you are being fooled into thinking you are getting more than a brief overview of what C++ offers.

I had to learn this the hard way, after discovering that only by reading multiple books works without having formal and extensive classroom instruction.

No single book/website covers for a beginner all of what C++ has to offer. For that matter even cppreference is lacking with some of the latest additions to the language. cppreference is not a site a beginner can learn C/C++ by reading the examples, it is primarily a reference site for experienced programmers, written and maintained by experienced programmers.

Learning C++ isn't easy, nor is it cheap if you buy books. Dead tree or eBooks.

And it will never stop, C++ will continue getting updates. C++23 is the current standard and people are already talking about C++26 features.

leanpub.com is a good source for eBooks self-published by well-respected programming authors, and others not so good authors. You have to know who to trust. One nice feature of leanpub is buying an eBook that is still being written. Free updates whenever the author makes corrections and/or additions

Now, I've said my piece, trying to help you from making the same mistakes I made. I'm done lecturing.
now any formatting errors are caught at compile-time


Yes for std::format()/std::format_to() where the format arg has to be compile-time evaluated, no for std::vformat()/std::vformat_to() where the format arg can be run-time evaluated (eg set by the program when it's being executed).
Peter, I think I understand now the issue with inlining, it is compile time vs run time and there is no sure way of predicting what the code is doing to be able to inline it during compile time. Since inlining is a compile time thing. Got it!

"A) "set" is a class that is templatized."

The official term is "class template".

In other words, std::set not a class. It's a template for generating classes.


Wanted to go book hunting to check...
Sam's book p496:

To use class std::set or std::multiset, include header:
#include <set>


Beginning C++20, p749:
"The second type argument of the std::set<> class template..."




"(SortDescend<int>) This sends in a type, which is REALLY a struct that is templatized for int type."

Template arguments are passed inside < and >. This is where you might find SortDescend<int>.


Got it, only inside <> and then it makes sense as a type sent to a class template.


Can you elaborate on this one a little bit more:
 
vector<int>::iterator iter;


"vector<int>" is the class template.
"::" is used because what is to the left of it is not an object, correct? Or is it ALSO that what is to the right of it is a type, in other words, "iterator" is a type also, this sentence is probably all incorrect.
What is "iterator" a struct within the vector class? It is not a static method that returns an iterator object or an enum, right? So it is just a struct within the class.






Thanks for the lecture, George. I am sure in due time I will have a larger book collection. One set at a time.
"vector<int>" is the class template.

No.

std::vector is a class template.

std::vector<int> is a class.

"::" is used because what is to the left of it is not an object, correct?

Yeah, we use :: to access things in classes that does not belong to any particular object. We also use :: to access things in namespaces.

"iterator" is a type also, this sentence is probably all incorrect.

This is correct. But note that the std::vector<int>:: in front is important. std::vector<int>::iterator and std::vector<double>::iterator are two different types.

What is "iterator" a struct within the vector class?

Yeah, it's a class within a class.

(Whether it's declared with the struct or class keyword doesn't matter.)
Last edited on

"The behavioral specifications and public members of the std::vector class are defined by
the C++ standard. Consequently,"(Sam's, p456)

"Standard Template Library (STL) supplies a ready-to-use solution in the form of the std::vector class."
(Sam's, p455)

"to obtain the size of just about any collection of elements defined by the Standard Library, including the std::vector<> and std::array<> containers" (Beginning C++ 20, p143)

"Like all containers, std::array<> and std::vector<> are defined as class templates" (Beginning C++ 20, p177)

"The vector<> container is discussed in the next section." (Beginning C++ 20, p181)


After reading my first book it is so highly ingrained in me to just call std::vector a class. One can also play on words here, "vector<> container". Well, if a container of vector is a class, then you should be able to say "vector<> class".

But yes, I think I get it. The compiler cannot make the full class until it has the type of container you want (vector, deque, list..etc) with the type of unit to store (int, char, long). When you have the two together, then you actually have a full class that the compiler can generate.

Recap:
std::vector //class template, container
std::vector<> //class template, container
std::vector<int> //class here (classes are types), a type here <int, vectorSort<int>>
std::vector<int>:: //Access to the class
std::vector<int>::iterator //Access to the struct/class within a class, a type
std::vector<int>::iterator iter //An object

Very good lessons here, thanks a million!
After reading my first book it is so highly ingrained in me to just call std::vector a class.

Yeah, people don't always express themselves precisely. And saying "class template" or "function template" when people might not even know what templates are could be more confusing than helpful. It's often implied that we're talking about a template instantiation (i.e. a class/function that is generated from the template). Usually there is no ambiguity because there is no way to create an object of a class template or call a function template without instantiating those templates.

Especially with function templates I think it's quite alright to say something like "Use the std::sort function to sort the vector" because when you use it it will be a function (you have just not specified which one).

1
2
std::vector<int> vec = {1, 3, 2};
std::sort(vec.begin(), vec.end()); // calls the function std::sort<std::vector<int>::iterator> 
Last edited on
After reading my first book it is so highly ingrained in me to just call std::vector a class.


http://kera.name/articles/2010/08/it-is-not-called-the-stl-mmkay/

https://stackoverflow.com/questions/5205491/whats-the-difference-between-stl-and-c-standard-library/5205571#5205571

Many hoo-man beans tend to be imprecise when it comes to technical language, which is not necessarily a completely bad thing as long as others understand (mostly) what is meant.

The best one can do is try to be as precise as possible.

What really can get mind-blowing is it is possible to instantiate a container such as a vector without explicitly declaring what type it will contain, courtesy of C++17's deduction guides, when the instantiation is done with an initializer list.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <vector>
#include <array>

int main( )
{
   std::vector vec { 1, 2, 3, 4, 5 };

   std::array arr { 1.2, 2.3, 3.4, 4.5, 5.6 };

   for ( const auto& itr : vec )
   {
      std::cout << itr << ' ';
   }
   std::cout << "\n\n";

   for ( const auto& itr : arr )
   {
      std::cout << itr << ' ';
   }
   std::cout << '\n';
}

http://coliru.stacked-crooked.com/a/bb234fe25f905b5c

std::array's formal initialization format has a rather verbose method compared to other containers IMO. Replace line 9 with the following to see what was required before C++17.

std::array<double, 5> arr { 1.2, 2.3, 3.4, 4.5, 5.6 };

Class template argument deduction really makes a difference when instantiating a container with an initializer list.

https://en.cppreference.com/w/cpp/language/class_template_argument_deduction
seeplus wrote:
Yes for std::format()/std::format_to() where the format arg has to be compile-time evaluated, no for std::vformat()/std::vformat_to() where the format arg can be run-time evaluated (eg set by the program when it's being executed).


I specifically said std::format, as shown in the examples from the Beginning C++20 book I've run across, in the chapters where trapping formatting errors was done by using try/catch blocks at run-time. If there are examples of std::vformat in the book I don't recall running across them. But then I doing yet another run-through the book and examples/solutions and picking up points of language usage I had either missed or not completely understood.

With that all said, your comment, seeplus, does have merit. :)

This is yet another example of a C++ standard being changed/improved after a book is written and published. The book does mention at the time of writing/publication no compiler was 100% C++20 compliant. Even now only Visual Studio is 100%, every other compiler has some deficiencies. Modules being "the biggie."

https://en.cppreference.com/w/cpp/compiler_support/20

The same for the Beginning C++23 book. AFAIK there isn't a single compiler that completely conforms to the standard.

https://en.cppreference.com/w/cpp/compiler_support/23

I should leave a note to the authors about that formatting change in C++20 since the code examples as shown in the book and on their official GitHub repo no longer compile. That can really frustrate a beginner.
Thanks George!
Class template argument deduction, auto, and range based for loops are great to know about and make life easier when in a rush. It also provides for much cleaner code, but I tend to prefer to do things the long way for practice. The short cuts make it too easy and so that is why most of my code samples will show the longer way.

I am glad to find out in this post that Class template argument deduction works and I was wondering why they did not program for it...until I changed my settings for C++ compiling and found out they did!
Any good C++ books that give you small sample assignments or mini projects? Bite size task to do and then give you the code for how they thought it should be done. For practice of what I know so far?
*cough*Beginning C++20*cough*

*Wanders off to do some mashing of sample code snippets using headers and module interface files*

https://github.com/GeorgePimpleton/module_testing
Any good C++ books that give you small sample assignments or mini projects?

Not a book, an online resource for learning C++.

https://www.learncpp.com/

It doesn't hurt that it is 100% free to read, with easy to digest lessons and lots and lots of code examples to try and mash on.
I bought that book George. In order to do the snippets of code you really have to read it and look at it (cheat) to see what is expected/requested of you. I just want a written request of a small project and I write it my way, then I compare mine to the books way of doing it to see how I might have improved it.

I found this book so far:
C++ In One Day: The Ultimate Beginners Guide To C++ With 7 Awesome Projects
By W.B Ean

Don't forget they are 7 AWESOME Projects! Such as a calculator, agenda, & note system. Honestly I prefer smaller and quicker tasks to learn more. Also, I think this one you may have to cheat by reading it and finding exactly what they want, rather than everything spelled out as a request before any code is shown.
The book "Practical C++ Design' is all about the design and coding of a calculator in 300 pages from simple text based to gui using qt. There's no exercises!

Seeplus, thanks. Looks good for a longer term project.
3) Why are there 3x destructors here? Is it because "for_each" makes 2x extra copies, and then there are a total of 3x instances of vector v1? If that is true, isn't this inefficient and why not pass by const reference?

I suppose it makes 2x copies internally using the copy constructor?
template< class InputIt, class UnaryFunction >
UnaryFunction for_each( InputIt first, InputIt last, UnaryFunction f );

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <iostream>
#include<vector>
#include<algorithm>
using namespace std;

template<typename elementType>
struct Display
{
	void operator()(const elementType& element) const
	{
		cout << element << endl;
	}

	~Display()
	{
		cout << endl << "**************" << endl;
	}
};

//struct Display
//{
//	void operator()(const int& element) const
//	{
//		cout << element << ' ';
//	}
//
//	~Display()
//	{
//		cout << endl << "**************" << endl;
//	}
//};

int main()
{
	vector<int> v1{ -4, 5, 6, 7, 99, -789,-44,541 };

	for_each(v1.cbegin(), v1.cend(), Display<int>());
	//for_each(v1.cbegin(), v1.cend(), Display());

	return 0;
}
/*
OUTPUT:
-4
5
6
7
99
-789
-44
541

**************

**************

**************

*/
Last edited on
Pages: 123