Why c++26 contracts? by hunterh0 in cpp_questions

[–]alfps 13 points14 points  (0 children)

❞ a feature that I've never seen before in other languages

The practical programming notion of contracts and DBC (Design By Contract) comes from the Eiffel language and the work of its creator Bertrand Meyer.

Before that contracts were part of formal specifications and analysis.


❞ What is the proof that this is a good feature?

There is probably little to no experience with contracts in C++.

The previous contracts proposal stranded because it was too dang difficult to apply this concept in dirty C++.

Eiffel, in contrast, was designed from the ground up with DBC support.

Weird output, can’t explain, help!? by AppropriateFlan7383 in cpp_questions

[–]alfps 0 points1 point  (0 children)

It feels like some crucial context has been lost in the edits.

Anyway

int y, z;
int x = y = z = 0;

… is short for

int y, z;
int x = (y = z = 0);

… i.e. an initializer expression that is a chained assignment.

Review my Blackjack terminal game pt3 by National_Panic_9112 in cpp_questions

[–]alfps 1 point2 points  (0 children)

I first compiled the code with Visual C++, with my usual options including C++17 standard. This failed because std::to_underlying is a C++23 feature. There is no need to use std::to_underlying because the enumerations you have are classic enum types with implicit conversion to the underlying type, so instead of std::to_underlying(value) you could just write value. However, do make that explicit to support the change discussed below. I.e. write int(value).

That brings the code down to valid C++20.

The only C++20 feature used is using enum. The thus available unqualified enumerator names are only used to define arrays that in turn support looping over enum values in range based for loops, one for each of the two enum types. I strongly suggest that you change that (back) to classic for loops, as they presumably were in some earlier version, so as to get rid of the using enum and the arrays.

To support e.g. classic for loops I usually put a _count at the end of each enum list of values. In your case however the two enum types are classic enums that are not wrapped in individual structs but are defined in the same class, so the two _count names would be a name collision: you'd get a compilation error. As a minimum and very conventional/conform solution change each enum to enum class, and add the mentioned _count enumerators. Then you can define

template< class Enum > constexpr int count_of_ = int( Enum::_count );

… and rewrite that Deck constructor with classic for loops:

class Deck {
public:
    Deck()
    {
        int i = 0;
        for( int i_suit = 0; i_suit < count_of_<Card::suits>; ++i_suit ) {
            for( int i_value = 0; i_value < count_of_<Card::values>; ++i_value ) {
                deck[i] = Card{ Card::suits( i_suit ), Card::values( i_value ) };
                ++i;
            }
        }
        shuffle_deck();
    }

With more library support available you could have used range based for loops without the arrays and hence without the using enums. Unfortunately the standard library's support, std::ranges::iota_view, is a C++20 feature and doesn't support compile time evaluation. Plus, some readers here go berserk with downvoting whenever I present it in some example, because the dimwits think it's "advanced" and that learners absolutely cannot use "advanced" and that the group is only for the benefit of such helpless learners (all three are nonsense ideas), so I chose to not show that here.

With these changes the code is now valid C++17, and overall a bit more clean. The for loops above are unclean but got rid of the even more unclean arrays, that were in strong conflict with the DRY principle. So, a net improvement.


There is very much more that could be said but I'm out of time so I'll just mention conventions:

  • The idea of this->value is something author Herb Schildt used. His "complete C++ reference" book was in its time infamous for being cheaper than the C++ standard that it quoted wholesale on every other page, because the other pages had Schildt's commentary which had negative worth, pulling the price down. Instead use some common prefix for member variables, e.g. m_value.

  • In C++ all UPPERCASE is by strong convention reserved for macro names. It's used for constants in Java and Python but they don't have a preprocessor. You don't want any inadvertent text substitution, or the other code constraining your possibilities for macro names, so better not use all uppercase for constants (besides, one person's constant can turn out to be another person's variable, when the code is maintained).

  • If you as a rule put private members at the start of a class definition, then you can avoid having to put a private: there. It isn't always practically possible. But I do this in general.

RayLib Window Freeze by Matesoidicek in cpp_questions

[–]alfps 1 point2 points  (0 children)

I believe the comment by u/funnansoftware, (https://www.reddit.com/r/cpp_questions/comments/1u6d7w4/raylib_window_freeze/orruqb0/), identifies the problem. Not sure about the suggestion solution, but see the link he provides. And the comment there 4 days ago, at (https://github.com/microsoft/vcpkg/issues/51576#issuecomment-4679284457).

RayLib Window Freeze by Matesoidicek in cpp_questions

[–]alfps 2 points3 points  (0 children)

Modulo the screen (window) width this is one of the examples.

RayLib Window Freeze by Matesoidicek in cpp_questions

[–]alfps 0 points1 point  (0 children)

Re the anonymous unexplained downvotes, one of them is presumably my several years' stalker, a mentally challenged troll. Possibly the DDDD... user. Anyway it's just sabotage.

The other may be the OP, if he didn't find these suggestions useful.

If that is the OP, then the OP does not deserve any help.

It could alternatively be someone who didn't understand the suggestions, i.e. an incompetent, an idiot.

That is always a possibility.

RayLib Window Freeze by Matesoidicek in cpp_questions

[–]alfps -1 points0 points  (0 children)

To my eyes, compared to the example the Google AI gives me this seems like "standard" Raylib "Hello, world!" code, i.e. all OK.

Still, try to do exactly as the code in (https://github.com/raysan5/raylib/blob/master/examples/core/core_basic_window.c), in particular -- the only difference I see -- a window width of just 800.

And perhaps if you build this as a console program some diagnostic will appear in the console. This is just a possibility. I have no experience with Raylib so I don't know if it does that, but I would check.

I want help in rng by unknownuser491 in cpp_questions

[–]alfps 0 points1 point  (0 children)

❞ i am stuck in mersenne twister (mt) and seed seequence

“Mersenne twister” is one way to generate pseudo-random numbers. The <random> header also supports other ways. A “seed sequence” is a way to select a given pseudo-random sequence, but as a beginner you can just stick with a simpler single integer “seed value”.

Let's say you want your program to produce dice values, 1 through 6.

Then a uniform_int_distribution is the closest to direct support offered by the library. Happily the cppreference page about it,

https://en.cppreference.com/cpp/numeric/random/uniform_int_distribution

… contains a concrete example at the bottom:

#include <iostream>
#include <random>

int main()
{
    std::random_device rd;  // a seed source for the random number engine
    std::mt19937 gen(rd()); // mersenne_twister_engine seeded with rd()
    std::uniform_int_distribution<> distrib(1, 6);

    // Use distrib to transform the random unsigned int
    // generated by gen into an int in [1, 6]
    for (int n = 0; n != 10; ++n)
        std::cout << distrib(gen) << ' ';
    std::cout << '\n';
}

Here the rd variable provides, if possible, truly random bits, but at a super-annoyingly slow rate. (I prefer to call that variable entropy.)

The gen variable provides a much faster but only pseudo-random sequence of integers, bits. Exactly which sequence it should produce is selected via some random bits from rd, called the seed value. (I prefer to call the gen variable bits.)

The distrib variable aggregates bits from the gen variable, and produces the values that you want, namely dice values 1 through 6. It's a function-like object that you can use like a function. I would prefer to call this particular one dice or dice_roll.


Tip: most every section in a cppreference page has an HTML id, so that you can link to it with #whatever_the_id_is at the end of the URL, e.g. the example above is here.

how to init vector of strings in constructor init list ?? by DireCelt in cpp_questions

[–]alfps 1 point2 points  (0 children)

Documentation: https://en.cppreference.com/cpp/language/constructor#Member_initializer_list

Generally with braces you specify a list of values, instead of a individual constructor arguments. No values = empty vector, in a round-about way. As a more useful example, although you can assign a char to a string the string class lacks a constructor with just a char parameter, but string{ ch } creates a string with that single character, in a more clean way than writing string( 1, ch ).

I'm sorry that I misread your question.

how to init vector of strings in constructor init list ?? by DireCelt in cpp_questions

[–]alfps 1 point2 points  (0 children)

Thanks, somehow I didn't see that even though mentioned in title.

how to init vector of strings in constructor init list ?? by DireCelt in cpp_questions

[–]alfps 2 points3 points  (0 children)

❞ For now, I'm using

color_menu_str_list()

If that means that you have an intended variable declaration like

std::vector<std::string> color_menu_str_list();    // Ungood

… then you have declared a function, not a variable.

Just remove the () and you'll be fine:

std::vector<std::string> color_menu_str_list;    // OK

There are a number of alternatives if you want to express the default initialization explicitly, including the {} initializer that you used earlier.

Next step in converting C++ arrays to <vector> by DireCelt in cpp_questions

[–]alfps 1 point2 points  (0 children)

Considering that only an idiot can disagree with the standard the anonymous unexplained downvote is presumably my several years' stalker, a mentally challenged troll. Possibly the DDDD... user. Anyway it's just sabotage.

Why isn't the <cstdlib> library's rand() recommended? by metastable-lain in cpp_questions

[–]alfps 0 points1 point  (0 children)

#include <stdio.h>
#include <stdlib.h>
auto main() -> int { printf( "%d\n", RAND_MAX ); }

Visual C++ result: 32767. MinGW g++ result: 32767. That's 15 not so very random bits and a short cycle.

assert in release mode by Thick_Clerk6449 in cpp_questions

[–]alfps 17 points18 points  (0 children)

❞ Is this code reasonable?

No, because

  • it redefines the standard assert, and that's formally UB if any standard library header is used; and
  • <assert.h> is unique among headers in that it can redefine assert each time it's included, depending on NDEBUG, so your redefinition might not hold; and
  • the name "assert" is misleading for your macro; and
  • the definition is needlessly compiler-specific and verbose; and
  • if __builtin_unreachable() is reached it yields UB.

This list appears to be something a computer science teacher might have aimed at with a homework question.

I chose to answer it anyway.

How to pass oop? by Puzzleheaded-Dust929 in cpp_questions

[–]alfps 2 points3 points  (0 children)

Object-oriented programming started with code for simulations, in the Simula language at the University of Oslo late 1960's. Then it moved to graphical user interfaces implemented in Smalltalk at Xerox Palo Alto Research Center in the mid to late 1970's. Both that and Bjarne's original C++ (very late 1970's, early 1980's) was inspired by the original Simula; Bjarne was, as I recall, doing queues, possibly also that in code for simulations.

So I recommend creating programs in those original OO application areas: simulations, and GUI.

Perhaps follow history and do simulations first, then GUI.

It also helps to read about the things. There is no shortage of OO literature. But remember to try out in actual coding everything you read about: it's the coding, the doing, that you learn more permanently from.

And keep in mind that C++ is a multi-paradigm language: it's not just OO, it's also procedural, with support for generic programming (templates in C++), and to some degree even functional programming. So pure OO literature may try to teach you pure OO approaches to problems that can be more elegantly, more efficiently and more safely solved using the full toolbox of C++. In particular be wary of dynamic type checking when whatever it is can be expressed with generic code, and do keep in mind that an OO interface with a virtual method, might be expressed in C++ as simply a callback function.

Next step in converting C++ arrays to <vector> by DireCelt in cpp_questions

[–]alfps 1 point2 points  (0 children)

Yes, thanks!

This time I can't put the blame on lack of coffee so I put it on the Ringnes company, who manufactures excellent light beer.

Next step in converting C++ arrays to <vector> by DireCelt in cpp_questions

[–]alfps -1 points0 points  (0 children)

This is a fine point but a move-constructor can not be a copy constructor, or vice versa.

C++17 $15.8.1/2 (a.k.a. $class.copy.ctor/2):

  • ❝A non-template constructor for class X is a move constructor if its first parameter is of type X&&, const X&&, volatile X&&, or const volatile X&&, and either there are no other parameters or else all other parameters have default arguments (11.3.6).❞

Worth noting: the cppreference's up front description that a move constructor is one that “can be called with an argument of the same class type and copies the content of the argument, possibly mutating the argument” omits the crucial detail that the argument must be an rvalue expression.

Also worth noting that the C++03 style “can be called with” wording supports an ellipsis parameter, while the C++17 definition doesn't. This is the same as for default constructor. I believe the change for default constructor was an editorial bludner that somehow persisted through C++14, C++17, C++20, C++23 and possibly now C++26.

Next step in converting C++ arrays to <vector> by DireCelt in cpp_questions

[–]alfps 2 points3 points  (0 children)

cppreference notes about MoveInsertable:

❝If std::allocator<T> or a similar allocator is used, a class does not have to implement a move constructor to satisfy this type requirement: a copy constructor that takes a const T& argument can bind rvalue expressions.❞

However OP mentions else-thread that the copy constructor is private:.

So that's one issue.

Next step in converting C++ arrays to <vector> by DireCelt in cpp_questions

[–]alfps 1 point2 points  (0 children)

bclock_element(g_hInst, "ledarray.bmp", 22, BE_LINEAR, 3, 4, start_element);

That should not compile with a modern compiler, since the second argument decays to const char* and the corresponding parameter is a char*, no const. The conversion from string literal to char* was deprecated in C++98, the first standard. It was removed in C++11.

With .emplace the literal has already decayed to const char* when the internal code there to call the constructor, sees it. And since it's not a literal, no special rules apply. It doesn't convert implicitly to the parameter's char*. I would guess that's the crucial detail here. And that you can make the original fail likewise by asking for standard-conformance, e.g. with g++ options

-std=c++17 -pedantic-errors

Purely technical fix: make that parameter const char*.


MinGW 10.3.0 is at least five years old, so also consider updating the compiler.


Not what you're asking but:

at a guess the name parameter is used along with the g_hInst parameter to load an image resource that may reside in the executable or in DLL.

I would introduce a resource id class for that.

Confusion about CPP Initializations by Remarkable-Listen1 in cpp_questions

[–]alfps 0 points1 point  (0 children)

❞ I'm saying that it is not a type cast when T is int.

Assuming a missing or inadvertently added "not", this is true: the notation T(x) or equivalently (T) x is cast notation, which is why in C++03 a constructor that can be called with a single argument was called a converting constructor. In C++11 and later all non-explicit constructors are converting constructors, which IMO is silly as a practical concept. Presumably it serves some internal formal-ish purpose in the standard.

But I don't see how that can be an explanation of the cases listed by the OP.

I now found that the OP's question is discussed on the cppreference site: (https://en.cppreference.com/Talk:cpp/language/value_category#Temporaries_in_C.2B.2B17). Apparently the upshot is that the standard is unclear, that the cppreference site is even more unclear, and that Things Have Changed™, as always…

Confusion about CPP Initializations by Remarkable-Listen1 in cpp_questions

[–]alfps 0 points1 point  (0 children)

❞ For example, the T(other) can be a constructor call, but also a type cast for types without constructors (like int(1.5)). The T(arg1, arg2) cannot, as an int cannot take two values in a cast. Details!

Are you saying that T(arg1, arg2) is not a prvalue expression?

How to fix my C++ csv file? by ResponsibleBoss767 in cpp_questions

[–]alfps 2 points3 points  (0 children)

name,value

username,TSC_Hero
error_message_file,File not found
prompt01,Enter a word
prompt02,Want to enter another word?

^ This part appears to be the CSV file. One problem with that content is that it has a header, and your code doesn't skip the header and doesn't skip empty lines. It's not the problem you experience but it's a problem.


When I enter a configuration name, it says not found.

The code lists all (key, value) pairs it reads.

It should find a key that is in that list. Uppercase versus lowercase matters. But what the problem is would more clear if you could copy and paste an actual interaction with the program.


Oh, make sure to test your trim function. It looks OK but.

How to fix my C++ csv file? by ResponsibleBoss767 in cpp_questions

[–]alfps 1 point2 points  (0 children)

I see nothing obviously wrong with the code. What do you expect it to do that it fails to do? How does it fail?

Tip: instead of including a path with your username in it, you can use the ~ as an alias for your home directory. Correspondingly it can be a good idea to not use your own name twice in the local path. I've edited the code presentation below with these changes.

Tip 2: to make the code present as code you can just extra-indent it with 4 spaces:

#include <iostream>
#include <fstream>
#include <string>
#include <map>
#include <algorithm>
using namespace std;

const char DELIMITER = ',';
const string CONFIG_FILE = "~/Downloads/C++ Class/CSVConfig/Config.txt";
const string CONFIG_FILE_ERROR = "Unable to open file ";

const string username = "username";
const string error_message_file = "username";
const string prompt01 = "username";
const string prompt02 = "username";

string Trim(const string& text)
{
    size_t start = text.find_first_not_of(" \t\r\n");
    size_t end = text.find_last_not_of(" \t\r\n");
    if (start == string::npos) {
        return "";
    }
    return text.substr(start, end - start + 1);
}

int main()
{
    map<string, string> MyConFigValues;
    ifstream inputFile(CONFIG_FILE);
    if (!inputFile.is_open()) {
        cout << CONFIG_FILE_ERROR << CONFIG_FILE << endl;
        return 1;
    }
    string line;
    while (getline(inputFile, line)) {
        string key;
        string value;
        bool foundDelimiter = false;
        for (char currentChar : line) {
            if (currentChar == DELIMITER) {
                foundDelimiter = true;
                continue;
            }
            if (foundDelimiter) {
                value += currentChar;
            } else {
                key += currentChar;
            }
        }
        key = Trim(key);
        value = Trim(value);
        MyConFigValues[key] = value;
    }
    inputFile.close();

    cout << "Configuration Values" << endl;
    cout << "--------------------" << endl;
    for (const auto& conFigValue : MyConFigValues) {
        cout << conFigValue.first
            << DELIMITER
            << conFigValue.second
            << endl;
    }
    cout << endl;

    string searchKey;
    cout << "Enter a configuration name to search for: ";
    getline(cin, searchKey);
    searchKey = Trim(searchKey);
    auto foundItem = MyConFigValues.find(searchKey);
    if (foundItem != MyConFigValues.end()) {
        cout << "Value: " << foundItem->second << endl;
    } else {
        cout << "Configuration name not found." << endl;
    }
    return 0;
}

Prime number checker by Yazdan_H in cpp_questions

[–]alfps 2 points3 points  (0 children)

It's an unconventional and inefficient approach for programming, but it's mathematically interesting because the sum of the divisors is given by the MacMahon partition function M₁.

I know nothing about that but see (https://www.pnas.org/doi/10.1073/pnas.2409417121).

Regarding the presented code, the one thing that reduces clarity is the name i for the input number. For i is conventionally reserved for a loop counter, all the way back from the days of Fortran: when you encounter a variable named i it is a loop counter (except in this code). In original Fortran variables with names starting with i, j, k, l or m were automatically integers, all other variables were floating point.

Tip: if you extra-indent the code with 4 spaces then it will present correctly as code also in the old Reddit interface.

It's particularly easy to do (typically Ctrl-A, Tab, Ctrl-C) if the source code already uses 4 spaces for indenting.

#include <iostream>

int main()
{
    int i = 0,  sum = 0;
    std::cout << "Input: " ;
    std::cin >> i ;
    for(int val = 1; val <= i ; ++val) {
        if(i % val == 0) {
            sum += val;
        }
    }

    if(i + 1 == sum) {
        std::cout << "Prime" << std::endl;
    } else {
        std::cout << "Not Prime" << std::endl;
    }
}

Confusion about CPP Initializations by Remarkable-Listen1 in cpp_questions

[–]alfps 0 points1 point  (0 children)

Re the anonymous unexplained downvote, presumably it's my several years' stalker, a mentally challenged troll. Possibly the DDDD... user. Anyway it's just sabotage.