C++ Review Questions

Pages: 1... 78910
Occasionally Visual Studio's Intellisense goes to lunch without telling anyone.

The amount of errors reported by Intellisense when using user created modules, errors that don't occur when actually compiling the code, is annoying at best. Frustrating even.

The same code, unchanged, sometimes there are errors from Intellisense, sometimes not.

'Tis deliciously risible you mention Singletons while I was doing some reading in the C++ Core Guidelines about Interfaces (I2 and I3 are related):

I.2: Avoid non- const global variables
http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Ri-global

I.3: Avoid singletons
http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Ri-singleton

Is there a way to get rid of the green squiggly line, a warning from Intellisense? Yup, shotgun blast it with a #pragma warning (disable : XXXXX) before the whinging line. XXXXX is the warning number, natch.

VERY non-standard C++.

Personally I don't usually do that, I prefer to notice if there are potential problems with my code that are illusionary when compiled.


Intellisense is as dumb as a rock at times.
Last edited on
Well, the book specifically says you don't have to define it, just declare it is good enough

To disable a particular function, declare that function as deleted:
1
2
3
4
5
6
7
class President
{
	President() = default;
	President(const President&) = delete;
	const President& operator = (const President&) = delete;
        // ...
};

That should get rid of the green squiggly, though there's nothing wrong with that code, it was idiomatic before C++11.
Last edited on
It does not produce a 5 digit error code though, no error...just that green squiggly line with 2 fix options...to auto create the definition or copy the signature to the clipboard.

No biggie though, no worries, I was just wondering.

@mbozzi
Yup, that worked...MAGIC!
Last edited on
Follow mbozzi's advice of marking the function(s) as default and deleted. My brain "Intellisensed" with my earlier answer.

Not all that surprising the Sams C++ book doesn't mention to mark class methods as default and deleted.
Last edited on
> frequent searches based on x position eventually, BUT the x position will change constantly & this cannot be used
> as key to lookup via set & map...because you cannot change them if they are used as keys in set & map.

We can unlink the node that contains the element of interest from the container, modify the the element in it and insert the modified node back into the container.
https://en.cppreference.com/w/cpp/container/node_handle

For example:

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
#include <iostream>
#include <random>
#include <vector>
#include <set>

struct Sprite
{
    int x = 0 ; // key
    int y = 0 ;
    // contains lots more stuff 
    // ...

    operator int() const noexcept { return x ; } // to support key compare using int
};

int main()
{
    // note: transparent key comparator
    std::multiset< Sprite, std::less<> > sprites ;

    // insert
    int y = 10 ;
    for( int x : { 1, 2, 1, 3, 4, 1, 5, 1, 6 } ) sprites.insert( { x, ++y } ) ;

    // lookup for x == 1
    for( auto [iter,end] = sprites.equal_range(1) ; iter != end ; ++iter )
        std::cout << "found Sprite with x,y == " << iter->x << ',' << iter->y << '\n' ;

    // modify a sprite
    std::cout << sprites.count(1) << ' ' << sprites.count(999) << '\n' ; // 4 0

    const auto iter = sprites.find(1) ; // find an element with key == 1
    if( iter != sprites.end() )
    {
        auto node_handle = sprites.extract(iter) ; // unlink the node from the set
        node_handle.value().x = 999 ; // modify the Sprite in it
        sprites.insert( std::move(node_handle) ) ; // link the node with the modified sprite into the set
    }

    std::cout << sprites.count(1) << ' ' << sprites.count(999) << '\n' ; // 3 1
}

https://coliru.stacked-crooked.com/a/2987989356ac528f

This would be more efficient if look ups are more frequent than modifications.
@JLBorges
Thanks. But I think it might bring it to a crawl the extraction & re-insertion. I will probably have 60-70 sprites on screen at a time & their positions will be changing constantly, but I will have many more already set & waiting on either end inactively. I will only have 2 columns of 6 sprites (12 sprites) checking for a range at a time & if they fall out of the range, they will pass it to the adjacent column of sprite (Left or right).
Can only 1 spirit at a time have the same x-pos?
> I will only have 2 columns of 6 sprites (12 sprites) checking for a range at a time

Yeah, for just that many do a brute force search.


> But I think it might bring it to a crawl the extraction & re-insertion.

It is actually quite a lot faster than what I suspect you imagine it to be.
https://coliru.stacked-crooked.com/a/7644d2bf5db89abb

What main C++ are the rest of you reading/have read? How much time have you spent on it & how long did it take you to learn it? How long do you think you will have to spend on the C++23 future book?


I'm not aware of any C++23 books yet (on either Amazon or leanpub.com).

At the moment, IMO the best on-line resource for C++23 is:
https://github.com/steve-downey/papers/blob/master/wg21-status.org

https://en.cppreference.com/w/cpp/compiler_support
gives a list of the C++23 features (and also those from previous versions and which compilers support what features [updated as/when] ). It also includes links to the C++ papers referencing each feature.
@JLBorges
I decided to end up trying more than one container for practice & I will definitely try your suggestion for multiset.
I love, "auto [iter,end] = sprites.equal_range(1)"... must be a C++20 lambda? Make an iter & use from begin to end to find "1" within that range. I just might shed a tear...imagine if it was this way from the start.

@seeplus
I know where you're getting at & I thought about that too. Problem is the image will be shifting at the bottom & scaling up/down & moving, AND the 6 will be slightly offset in x distance for a period of time. But yea I could try to use only 1 of the 6 to track for the leading one. It might work, I just have to see how well it does on the edges.

Yea, I have not seen any full C++23 books either, but I mean when you guys get them. Even the C++20 as some might not have completely covered them. Just curious how long it will take a professional programmer going through a C++20 or C++23 book....a year or 2 to fully understand the new concepts?

Sam's book that covers "some" C++23
https://www.oreilly.com/library/view/sams-teach-yourself/9780137334674/

Oh & you bastard! You now made me get Professional C++ 5th Edition by Marc Gregoire. I read a snippet from the book & you're right, soo good...1300++ pages (insert crying emoji here).
Last edited on
auto [iter, end] = sprites.equal_range(1); looks like it's a structured binding declaration, introduced in C++17.

https://en.cppreference.com/w/cpp/language/structured_binding

A lambda expression is an entirely different critter.

https://en.cppreference.com/w/cpp/language/lambda
Last edited on
> "auto [iter,end] = sprites.equal_range(1)"... must be a C++20 lambda?

sprites.equal_range(1) uses the templated overload for generic lookup.
Overload (3): https://en.cppreference.com/w/cpp/container/multiset/equal_range.
It allows us to perform a lookup without constructing a full Sprite as the key. This came with C++14. Note that for this to work, we need to use a transparent key comparator; typically we would use std::less<> as in the snippet.

equal_range(1) returns a pair of iterators;
auto [iter,end] = sprites.equal_range(1); uses a structured binding declaration. https://en.cppreference.com/w/cpp/language/structured_binding This came with C++17.
Hmm, I guess I let my imagination go wild then as I have seen the subscript operator [] in array notations & lambdas and figured it must be some new lambda condensed notation to create a struct & and iterate in there somehow for the range find & return an iterator.

I just did a search in my 1st book on structured binding & nothing, but it is in my 2nd book though. Good to know, thanks.
many, many operators have multiple meanings. * is pointer or multiply. & is bitwise and as well as address-of as well as a reference. >> are both streams and bit-shift. Just a few quick examples, there are plenty more.... try to not get caught up on such things (it can be hard at first). There are a limited number of code friendly symbols and more things you want to do than there are good symbols for them, so they get reused.

Personally I dislike the [] lambda thing. I am sure there was some great reason for it, but I still don't care for that syntax. C++ has quite a few syntax things that were not well thought out before being added, like the stream modifiers that are really functions but look like variables. how you gonna know that this:
cout << hex << z;
is nothing at all like
cout << plex << y;
without memorizing a list of special codes?
Last edited on
Thanks Jonnin & I am aware of that. Up to that point I did not know the single bracket [] pair was actually used for anything else just like I cannot assume now that the * is used for anything other than pointer/dereference/multiplication, until they change something & I eventually discover otherwise

So in my first book I never encountered [[ ]] the double bracket, & in my 2nd book I only read to chapt 5 so far. On p129 it says "you can add a [[fallthrough]] statement in the same
place where you would otherwise add a break statement:". Where did this beast come from, not that I will use it any time soon, but good to know for a switch statement. Then I wonder will I see that notation anywhere else, or is it a one time deal for switch's?

Now yesterday my Professional C++ 5th ed book just arrived in the mail & I was super excited to read it & I read the 1st 30+ pages. Come to find out they are actually called "attributes" & that there is more of them. Alright, so now I can officially add [[ ]] syntax to mean something to C++.

While we are on the subject of lambda's, and mind you I only read about them from my 1st book so far & have limited exposure, can they be used outside of algorithms? I know they shorten the code for what can already be written in structs & classes and they work on unary & binary functions/predicates. Are they only there for inputs to parameters on algorithms?
Are they only there for inputs to parameters on algorithms?


No. As an example which calculates factorials:

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>

int main() {
	constexpr auto factorial { [](uint64_t n) noexcept {
		constexpr auto f_impl {[](uint64_t n, const auto& impl) noexcept -> uint64_t {
			return n > 1 ? n * impl(n - 1, impl) : 1;
		}};
		return f_impl(n, f_impl);
	} };

	std::cout <<  factorial(5) << '\n';
}


For the last word on lambdas, see:
https://leanpub.com/cpplambda
CoreGuidelines:

T.141: Use an unnamed lambda if you need a simple function object in one place only
http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rt-lambda

F.50: Use a lambda when a function won’t do (to capture local variables, or to write a local function
http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-capture-vs-overload

ES.28: Use lambdas for complex initialization, especially of const variables
http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-lambda-init
Thanks.

I ordered the Lambda book, gonna need it.
Incidentally, I just read about structured bindings in Professional C++ p38 covers it.

QUESTION 13)
Is it possible to add a template to a singleton? I have not done templates on header files before, but I was able to get this far. It compiles with errors "3 unresolved externals"
I know the compiler has to resolve the templates, but on singletons..tricky business???

With this line, looks like I am asking to use <T> without it even first having made an instance of the class...no good.
 
static President<T> onlyInstance;


But I really don't want to use the line below as it defeats the purpose & it does not work anyway.
 
static President<vector<string>> onlyInstance;


"unresolved external symbol "public: static class President<class std::vector<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > > > & __cdecl President<class std::vector<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > > >::GetInstance(void)" (?GetInstance@?$President@V?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@std@@@@SAAAV1@XZ) referenced in function _main"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <string>
#include <vector>
#include "President.h"

using namespace std;

int main()
{
	President<vector<string>>& onlyPresident = 
                 President<vector<string>>::GetInstance();				
	//President& onlyPresident = onlyPresident.GetInstance(); 
	onlyPresident.SetName("Abe Lincoln");

	cout << President<vector<string>>::GetInstance().GetName() << endl;
	cout << onlyPresident.GetName() << endl; 
	cout << onlyPresident.GetInstance().GetName() << endl; 
}


President.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#pragma once
///#pragma warning (disable : XXXXX)
#include <string>
using namespace std;

template<typename T>
class President
{
	President() {}; //private default constructor
	President(const President&); //private copy constructor
	const President& operator = (const President&) = delete; // assignment operator

	string name;
	T containerFormerPresidents;

public:
	static President<T>& GetInstance();

	const string GetName() const;

	void SetName(string inputName);

};


President.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "President.h"

template<typename T>
President<T>& President<T>::GetInstance()
{
	//static ensures only happens once 	
	static President<T> onlyInstance;
	//static President<vector<string>> onlyInstance;
	return onlyInstance;
}

template<typename T>
const string President<T>::GetName() const
{
	return name;
}

template<typename T>
void President<T>::SetName(string inputName)
{
	name = inputName;
}
Last edited on
With templates, one can't separate the header and cpp files, put all of it in the header file. :+)
Pages: 1... 78910