C++ Review Questions

Pages: 123... 10
Restarting my review question list with hopefully shorter & simpler questions that I had when reading about C++ in my book.

QUESTION 1)
In method DisplayContents2, if I did not want to use auto or list<int>, how could I get either of these two to work?

list<T>::const_iterator element = container.cbegin(); //NOT WORK
list<typename T>::const_iterator element = container.cbegin(); //NOT WORK


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
#include <iostream>
#include <list>
using namespace std;

template<typename T>
void DisplayContents(const T& container)
{
	typename T::const_iterator element = container.cbegin();	
	for (element ; element != container.cend(); ++element)
		cout << *element << ", ";
	cout << endl;
}

template<typename T>
void DisplayContents2(const list<T>& container)
{
	//list<T>::const_iterator element = container.cbegin();		//NOT WORK
	list<typename T>::const_iterator element = container.cbegin();	//NOT WORK
	//list<int>::const_iterator element = container.cbegin();	//WORKS
	//auto element = container.cbegin();					//WORKS
	for (element; element != container.cend(); ++element)
		cout << *element << ", ";
	cout << endl;
}

int main()
{
	list<int> linkInts{ -99, 16, 987 };
	DisplayContents(linkInts);

	list<int> linkInts2{ -99, 16, 987 };
	DisplayContents2(linkInts2);


	return 0;
}
Last edited on
1
2
3
4
5
6
7
8
template< typename T >
void DisplayContents2( const std::list<T>& container )
{
    typename std::list<T>::const_iterator iter = container.cbegin() ;
    const typename std::list<T>::const_iterator end = container.cend() ;

	// ...
}
^^^ the compiler on this site actually tells you this explicitly, if you read the spew.
(for the <t> version you commented out, at least, it gives the message:
note: say 'typename std::list<T>::const_iterator' if a type is meant
Last edited on
Also see the 'Down with typename!' proposal P0634
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0634r3.html

and changes in C++20:
In some contexts, only type names can validly appear. In these contexts, a dependent qualified name is assumed to name a type and no typename is required (since C++20)
https://en.cppreference.com/w/cpp/language/dependent_name#The_typename_disambiguator_for_dependent_names
Thanks.
I actually did get a compile message & so then I added "list<typename T>" there. Placing typename in front did not make any sense at the time....but in your linked documentation it clearly states..."where T is a template parameter — is to denote a type, it must be preceded by the keyword typename"

I have a really hard time reading documentation depending on what I am looking for. Sometimes I can gather the info just fine, other times the doc seems very ambiguous to me and I end up having more questions than answers. At what point do the documentations become easier to read, how long did that take you guys?

Let me just take one step back to make sure I know how the part that works actually functions >>> In the 1st method, "void DisplayContents(const T& container)" T is "list<int>" and this line:
 
typename T::const_iterator element = container.cbegin();


Is read as if it is the line below, right?
 
list<int>::const_iterator element = container.cbegin();



Now, with the 2nd method:
template<typename T> //T= list<int>
void DisplayContents2(const list<T>& container)
_______________________^^^^^ your telling me here that "T= list<int>" is deduced to "T=int" like "MAGIC"? The code is telling me that, because it just works.
> "T= list<int>" is deduced to "T=int" like "MAGIC"?

There is no magic. The compiler deduces the type by figuring out what type can be substituted for the template parameter T to get a match between std::list<int> and const list<T>&.

Given a function parameter P that depends on one or more type template parameters T ... and the corresponding argument A, deduction takes place if P has one of the following forms:
...
class-template-name<T>
...
https://en.cppreference.com/w/cpp/language/template_argument_deduction#Deduction_from_a_type


In our case, the class template is std::list, P is std::list<T> and A is std::list<int>



You may want to skip this part right now.

Some adjustments may be made to P and A as detailed here:
"Before deduction begins, the following adjustments to P and A are made: ..."
https://en.cppreference.com/w/cpp/language/template_argument_deduction#Deduction_from_a_function_call

And there are some Non-deduced contexts.
https://en.cppreference.com/w/cpp/language/template_argument_deduction#Non-deduced_contexts
Thanks, I appreciate it.

No, I know that there is no magic, but "SMART" or "MAGIC" is my reference to the compiler algorithms and logic behind the usage and deduction, when I am trying to be cynical. Reading books and regurgitating examples is sometimes not good enough. When steering off course one will see how the compiler may not interpret things so simplistically...or at least what may seem simplistic on the surface.

A few times already it has happened when I read the book, do the sample problem and I am able to repeat it without looking. Then once in a while I change a parameter or start to wonder how this is really working behind the scenes, and a whole new world opens up as exposed by you fine people. It makes me realize each time that I have a false illusion of knowing parts of C++ and it makes me wonder how many more dozens of things that I really don't fully understand.

void DisplayContents2(const list<T>& container)
_______________________^^^^^ works like "MAGIC" here, but....

list<T>::const_iterator element = container.cbegin();
___^^ don't even think about it here buddy, no "MAGIC" for you...you have to say pretty please with typename in front...

typename list<T>::const_iterator element = container.cbegin();


That was just me being serious and seriously cynical and getting things off my chest. I think I understand why they had to do this though...because if you really wanted a list of list<int>'s then you need a way to differentiate them.
list<T>.....to mean..... list<list<int>>

I think after I finish my review, I will have to tackle documentation and I will dissect and analyze one document at a time to get better. Right now, I have seen too many new things and I need to sort them before needing to ask more questions from documentation. I sure hope it gets easier over time, as it has for me looking at the items through my book.
Last edited on
The way I think about it is the following.

You have already told the compiler that T is a type so you don't need to do that again.
 
template<typename T>

Knowing that list<T> is a type is also straight forward because std::list is a class template.

But when the compiler sees something like
 
list<T>::const_iterator
it doesn't know whether it should treat it as a type or not. It might also be a variable or function.

It might seem trivial for the compiler to just look at the definition of std::list to see if const_iterator is a type. The problem with that is that technically it could mean different things for different T thanks to template specialization. For example, list<int>::const_iterator could be a type while list<double>::const_iterator could be a function. We know that's not the case but the compiler can't assume that. That's why we need to tell the compiler that it is a type (by using typename) otherwise it will assume that it's not (because that's the default assumption).
Last edited on
Thanks Peter, that is a good way of looking at it.

QUESTION 2)

When I first learned about C++ it was said I need to place the header files atop the code and that it was a preprocessor directive that allows my program to "use" or "utilize" the code. Much later I find out that it actually COPIES the header files in my code and has a linker...etc. It copies just the header & not the .cpp part, right? The .cpp file for the .h file goes right to step 2 if I am understanding this correctly?

When they say "library" in step 3, they mean all libraries of types (a,b, & c), not just the standard library, correct? So all three of these (a,b, & c) start at step 1, even the standard library (i.e. stdlib need to have their .h files copied to main & .cpp compiled on step 2 (pre C++20))?

a) class1.h / class1.cpp
b) "Boost" library
c)#include <iostream>
#include <vector>

Forget for a moment the various possible file extensions for this:
1) IF
class1.h/class1.cpp file then copy .h file into main.cpp & utilize it's class1.cpp file in step 2.
ELSE
module goes right to step 2.

2) Compile all .cpp files to create object files (.obj/.o, that is the machine code).

3) Linker links all object files with the library to step 4

4) Executable created
The way we use includes and split code into .h and .cpp files is mostly just convention. It doesn't have to be done that way. But there are good reasons to do it that way because it has been proven to work well over the decades that C and C++ have existed.

Including a file always works the same way. It just includes the content of that file as if you had written the code in that file directly in that location (except things like __FILE__, __LINE__ and std::source_location::current()).

The content of a .cpp file together with all the content that it includes is normally referred to as a compilation unit. Each compilation unit is compiled separately without knowledge of any other compilation unit. When all compilation units have been compiled the result is linked together to create an executable file.

When you have other libraries (the standard library, SFML, ncurses, etc.) the .cpp/.c files of those libraries are often pre-compiled so that you don't have to compile them yourself. However, the library header files will still be compiled as part of each translation unit that includes them.

Libraries can be linked statically or dynamically. Static linking means the compiled library code is bundled together inside the executable file. Dynamic linking means the compiled library code is stored separately [e.g. in a DLL file on Windows]. There are pros and cons to both approaches.
Last edited on
@protoseep - if you're going to ask multiple questions, would you either ask them in the first post or start a new thread for each question.
@seeplus

seeplus wrote:
@protoseep - if you're going to ask multiple questions, would you either ask them in the first post or start a new thread for each question.


I would rather 1 topic for all the questions, it keeps them all in one place rather than a whole bunch of new topics.
Thanks Peter, it makes even more sense now. I had read some chat that mentions static/dynamic lib and was wondering what it all meant, it is essential to know thanks.

Sorry seeplus, I really would love to have them in 1 place to help me better access them, than all over the place. A lot of the questions should be very simple in fact and may help out other newbs if they were in one spot as well.

I really wish there was one set of books that does an exceptional job of explaining things in detail. Something like read the intro to each topic to get a full understanding, then put in an EXTRA section where there is additional info for when you are comfortable with the intro material, and then a PITFALLS sections that describes the many nuances and discrepancies of that topic. I would not mind if the set was 4-6 books long. Then a more extensive Q/A and ToDo projects with solutions. But, instead you have to piece meal it.

Today I viewed 3x videos on templates, and for the most part I knew the info and it was a waste of time and did not cover the questions that I had asked on my other posts & here. I did learn from this one instructor that templates are not to be included in a .cpp file and should be included in a .h header file instead. He also said that there are unpredictable hacks, such as putting them in a custom name file (.t). But that was about all I learned & I will next just read another book on templates to see what else I can pick up.

I think those types of Udemy/Youtube intro and even intermediate videos are too simplistic now. Even college intro courses will not cover this material that you guys are exposing me to.
For a book on templates, consider:

C++ Templates - The Complete Guide (second edition) by Nicolai Josuttis
https://smile.amazon.co.uk/Templates-Complete-Guide-David-Vandevoorde/dp/0321714121/ref=sr_1_1

Covers C++17.

IMO one of the 'problems' with templated code are the error messages produced by the compiler when the syntax used isn't quite right. These can be pretty 'impenetrable' to understand what is the issue. Surely with now 'mature' C++ compilers, it's not beyond the limits of compiler writers to produce an initial meaningful error message and suggestion(s) for a fix. I remember from many, many years ago working on this type of issue when I was doing compiler work with Pascal and later with Pick Basic...
Last edited on
Templated code that is to be used in more than one compilation code is usually put into a separate file and included at the beginning of the appropriate .cpp file. Note that the extension of an include file can be really whatever. There is a convention that .h are for header files but many use .hpp where the header file also includes actual c++ code as opposed to just declarations (like templated code). But there are no restrictions on this. The pre-processor just reads the contents of the specified file and inserts it's contents into the file to be compiled in place of the #include. Note that #include statements can go anywhere in a program - not just at the beginning. Also #include files can also contain #include which can contain... You can even include .cpp files within other .cpp files - although this would probably cause 'raised eyebrows'. Only once has all the #include's been processed - and all other pre-processor directives - does the compiler start to compile the resultant code.
Two books mention two different sets already (.c, .cp, & .cpp) and (.cc, .cxx, .c++) and by now I am sure other books might mention different ones.

That seems like a must read, I will add it to my list...whoa 832 pages just on templates...it's times like these I wish I was a savant!

No wonder you guys are so good and probably read whatever you can get your hands on.
> Two books mention two different sets already (.c, .cp, & .cpp) and (.cc, .cxx, .c++)
> by now I am sure other books might mention different ones.

Many different ones. For example, GCC default (without a -x language option) assumes:

file.h - C or C++ header file ...

file.hh, file.H, file.hp, file.hxx, file.hpp, file.HPP, file.h++, file.tcc - C++ header file...

file.c - C source code that must be preprocessed.

file.i - C source code that should not be preprocessed.

file.cc, file.cp, file.cxx, file.cpp, file.CPP, file.c++, file.C - C++ source code that must be preprocessed.
Note that in ‘.cxx’, the last two letters must both be literally ‘x’. Likewise, ‘.C’ refers to a literal capital C.

file.ii - C++ source code that should not be preprocessed.
https://gcc.gnu.org/onlinedocs/gcc/Overall-Options.html#Overall-Options
> .whoa 832 pages just on templates...

It tries to cover everything and everything about templates, and IMHO does so in a far too verbose manner. Quite useful for people who design and write non-trivial template libraries. For normal programmers? I'm not so sure. You do not need to master every dark nook and corner of the language to become a competent C++ programmer.
Yep, exactly what I mean...spend time with you guys & you open up a whole new world in a topic. So, files created in GCC can be opened up in MS VS, but the extensions won't necessarily carry over the same compiler meaning/translation into VS, right?

I will get a snippet of the book & see if it fits me, but thanks for the warning as I cannot handle verbose & loftiness for now when I am trying to figure things out.

@seeplus
Why do you think templated error codes are so cryptic? Why would they do that? Is it just someone or a group of people caught up in their own ways?
The file extensions are conventions/conveniences to make it easier for us hoo-mans to differentiate what a file contains. To the preprocessor/compiler a file extension doesn't mean anything.

When it comes to modules everyone but MS so far is leaning towards using .cppm to designate a module interface file, .cpp for an internal partition file OR module code (/interface, the same as .cppm)

MS likes .ixx for a module interface file, though Visual Studio recognizes .cppm.

To get VS to recognize a file as an internal partition one of the file's properties must be manually modified in the IDE. I don't know how to do this with the command-line compiling tools.

The VS IDE sorts the files in Solution Explorer based on the file's extension, for easier management of a project with multiple files. Console-mode programs with routine file extensions get sorted into header and source file sub-categories.

Module interface and partition files are sorted into the source file sub-category exclusively.

VS treats even module-free C++ code as defaulted to a module interface file, that can be set to compile as C++ code manually.
1
2
3
4
5
6
#include <iostream>

int main()
{
   std::cout << "Hello World!\n";
}

When compiled as a module interface file there are additional compilation steps that occur. When the above snippet is compiled as C++ code (/TP):
Build started...
1>------ Build started: Project: Project1, Configuration: Debug x64 ------
1>Source.cpp
1>Project1.vcxproj -> C:\Programming\My Projects\Project1\x64\Debug\Project1.exe
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

When compiled as C++ module code:
Build started...
1>------ Build started: Project: Project1, Configuration: Debug x64 ------
1>Scanning sources for module dependencies...
1>Source.cpp
1>Compiling...
1>Source.cpp
1>Project1.vcxproj -> C:\Programming\My Projects\Project1\x64\Debug\Project1.exe
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

Importing stdlib library headers as modules (import <iostream>; instead of #include <iostream> ) and custom created module interface/partition files adds even more module dependency scanning. Even the stdlib modules require being compiled the first time or during a complete rebuild.

Headers and module interface files are similar in what they do, but they are most certainly not the same.

Tattoo that on the back of your eyelids and learning to use modules will become easier. Still a major shift of thinking, but not as frustrating as thinking modules and headers are the same.

No other compiler at present other than VS supports modules, so I can't say how they would work when consuming modules.

Personal tastes...

I prefer .h/.c for C, .hpp/.cpp for no modules C++.

When it comes to C++ code using modules it is .cppm and .cpp. I loath .ixx and will probably never use it.

Of course, using modules requires the C++ language standard for the entire solution/project to be set to C++20 (std:c++20) or higher. Higher at this time is std:c++latest. When VS implements C++23 then eventually having C++23 as a language standard option should become available.
Last edited on
Pages: 123... 10