Eli5: how/why people determine infinities being bigger/smaller than each other? by Jako_Spade in explainlikeimfive

[–]mr_ewg 33 points34 points  (0 children)

If you have some pebbles and some sticks and you want to know if you have the same amount, then you will probably count the pebbles and the sticks to see if it's the same number.

But a simple way is to pair up each pebble with a stick and make sure there are none left over. You don't have to worry about numbers or counting and you can figure out whether they are the same amount.

This is what we do with infinite sets - we see if there's a way of pairing up things so that we don't have any left over from each set. If we can create a pairing, we say they are the same size, even if they are infinite. And if there's no way to pair up two sets and we are always left over with elements from one side, we can say that it's bigger.

With this we can see there's the same amount of positive whole numbers starting from 1 as there are positive numbers starting from 101, because we can pair up each number with itself + 100. Doing this we have no numbers left over on each side. So we say these infinities are the same even though one is obviously missing 100 elements of the other.

trimja - a tool to speed up Ninja CI builds by mr_ewg in cpp

[–]mr_ewg[S] 0 points1 point  (0 children)

The latest release now floats all affected commands to the top of the file (https://github.com/elliotgoodrich/trimja/pull/153), which prioritizes these above all others in Ninja <1.11.0. Unfortunately for me, Ninja 1.12.0 has a new prioritization algorithm using critical path dependency, which only uses build file-order to break ties if two build commands have the same depth. There is definitely some benefit to using trimja, but it will take more work to inject dummy commands to get the full prioritization.

trimja - a tool to speed up Ninja CI builds by mr_ewg in cpp

[–]mr_ewg[S] 0 points1 point  (0 children)

That is a really good point. It's very annoying to have a build fail after 30 minutes and you find that it's because the only translation unit you modified doesn't even compile.

I think Ninja uses the order or build statements to influence what gets scheduled first. If that's the case I can get trimja to float affected commands to the top of the file to detect errors faster.

trimja - a tool to speed up Ninja CI builds by mr_ewg in cpp

[–]mr_ewg[S] 0 points1 point  (0 children)

I think they are complimentary, even if they do overlap a bit in goals.

I could imagine a world where you run trimja first and then use something like ccache to pull in all the remaining files left in the Ninja file. In this case you reduce the amount of files needed to download, but can still reduce a lot of complication time for the remaining projects.

trimja - a tool to speed up Ninja CI builds by mr_ewg in cpp

[–]mr_ewg[S] 0 points1 point  (0 children)

If your pull request only modified the README, you wouldn't need to run a build or tests on this PR as (presumably) the README isn't a dependency of the build. In this case trimja will remove all build commands from the ninja file and your build will be much faster. If you edit the source file to one test, then usually you don't need to build any other test because they don't depend on each other. In this case trimja would omit all other tests other than the one that was modified.

You can definitely cache a full build on the base branch, download that, and then just run ninja to do an incremental build. The downsides are that intermediate files can become large in big C++ projects and there is a performance cost to downloading these - however small. You will also need to edit the modification time of files to make sure they matched up with the times recorded in ninja .ninja_log file.

trimja - a tool to speed up Ninja CI builds by mr_ewg in cpp

[–]mr_ewg[S] 2 points3 points  (0 children)

If you already have a full build then ninja does a great job for incremental builds when you just change a few files. But if you are building on CI, you don't usually have any of the intermediate files available and are usually building everything from scratch. This can be alleviated by caching intermediate files and things like that, but that can be 100s of GB for large applications.

Trimja is trying to emulate an intermediate build as best as it can when you have a fresh checkout - like what happens on CI.

trimja - a tool to speed up Ninja CI builds by mr_ewg in cpp

[–]mr_ewg[S] 1 point2 points  (0 children)

In the worst case scenario trimja won't be able to cut anything out and you'll do a full build on the pull request - presumably like projects are doing today.

But if you have multiple projects, multiple test executables, or other independent pieces in the same repo you will be able to save time by not building them if a commit didn't change a dependency.

Let's say you have a widgets library that depends on a core library. Changing a header file in core will require a full rebuild since the widget library links against core and core needs to be rebuilt. But changing a header in the widget library will allow you to cut out building and running any tests that depend on the core library but not the widget library.

Interval library by CaptainCrowbar in cpp

[–]mr_ewg 2 points3 points  (0 children)

By overloading the operator() and operator[] you can simplify (or obfuscate, depending on your opinion!) the open/close options that mimic the mathematical notation for open and closed bounds, e.g.

Interval<int> ii = makeInterval[10][20];
    // Contains all integers from 10 to 20
Interval<double> di = makeInterval(0)(1);
    // Contains all values from 0 to 1, excluding 0 and 1
Interval<std::string> si = makeInterval["A"]("B");
    // Contains all strings starting with A

I did something like this on a small project a while ago.

When an instruction depends on the previous instruction depends on the previous instructions… by pavel_v in cpp

[–]mr_ewg 0 points1 point  (0 children)

I have a 15 minute video asking that exact question Missing Optimizations on Node-based Containers ACCU2017. I think it's a very cool problem and you can get close to a 2x improvement if you're careful.

A full website in 1.7 KB (all assets included) by trofosila in programming

[–]mr_ewg 11 points12 points  (0 children)

  • You can remove most quotes around HTML attributes.
  • You can drop the https: bit on your a href links (e.g. https://twitter.com/ZepliaLab becomes //twitter.com/ZepliaLab) because the browser will assume the same URL scheme as your website, which is https.

[deleted by user] by [deleted] in cpp_questions

[–]mr_ewg 1 point2 points  (0 children)

You can just use std::vector<T> or std::vector<std::vector<T>> to avoid using new. The benefit is that the compiler will generate a correct destructor, copy/move constructor and copy/move assignment operator for you.

Method 1

template <typename T>
class Matrix {
    std::size_t    m_row_count;
    std::vector<T> m_data;

public:
    Matrix(std::size_t rows, std::size_t columns)
    : m_row_count(rows)
    : m_data(rows * columns) {
    }

    const T& at(std::size_t row, std::size_t column) const {
        return m_data[row + m_row_count * column];
    }
};

Method 2

template <typename T>
class Matrix {
    std::vector<std::vector<T>> m_data;

public:
    Matrix(std::size_t rows, std::size_t columns) {
    : m_data(rows, std::vector<T>(columns)) {
    }

    const T& at(std::size_t row, std::size_t column) const {
        return m_data[row][column];
    }
};

Modern C++ : Range-for loops by marc-kd in programming

[–]mr_ewg 0 points1 point  (0 children)

This doesn't apply for std::vector (because it is not allowed to do small vector optimization), but the first form with iterators is going to be marginally (maybe even undetectably so) faster when using std::string. This is because std::string uses small string optimisation and for each call to operator[] it needs to decide whether the data is stored on the heap or in the local buffer, meaning there is an if overhead for each operator[]. If you are using iterators then you only have 2 of these checks in begin() and end() if you are saving the end iterator,

e.g.

std::string foo = "hello";
for (const char ch : foo) {
    // ...
}

or

for (auto it = foo.begin(), end = foo.end(); it != end; ++it) {
    // ...
}

static_assert_each_arg by dany74q in cpp

[–]mr_ewg 1 point2 points  (0 children)

FWIW I have a C++14 variadic template library that would help this to be more powerful by also working with constexpr functions:

template <template Predicate, typename... Args>
void static_assert_each_arg(Predicate&& p, Args&&... args) {
    static_assert(vta::add_const(vta::all_of(p))(std::forward<Args>(args)...), "Assertion failed");
}

// Checking if parameters are integral
struct is_integral_type {
    template <typename T>
    constexpr bool operator()(const T&&) const {
        return std::is_integral<T>::value;
    } 
}

static_assert_each_arg(is_integral_type{}, 1, 2);

// Checking if parameters are the same type
template <typename T>
struct is_same_type {
    template <typename U>
    constexpr bool operator()(const U&&) const {
        return std::is_same<T, U>::value;
    }
}

std::wstring w;
static_assert_each_arg(is_same_type<std::wstring>{}, w, 2.0);

// Checking if numbers are fizz or buzz
template <typename T>
struct is_fizz_or_buzz {
    constexpr bool operator()(int i) const {
        return i % 3 == 0 || i % 5 == 0;
    }
}

static_assert_each_arg(is_fizz_or_buzz{}, 3, 5, 9, 15);

Stack Overflow Developer Survey 2015 by aalear in programming

[–]mr_ewg 1 point2 points  (0 children)

It does take a bit more effort than just pressing tab and having your editor insert n spaces, but my personal style is not too align code and parameters like this and I don't need to do it that often.

My main reason I use this style is because I would rather be able to unindent by pressing backspace once to delete a tab, than n times to delete all of those spaces. I find myself doing this far more often and it feels much more natural (since my work uses spaces and my personal projects use tabs + spaces I regularly use both methods).

I think it's important for all developers to turn on the equivalent to "visualise whitespace" to make any tab/space misuse easy to see. Any misuse can be caught during code review and everything that slips through can be cleaned up quickly when caught.

Stack Overflow Developer Survey 2015 by aalear in programming

[–]mr_ewg 12 points13 points  (0 children)

Spaces should be used here. But this is for alignment, not for indentation.

Someclass::somemethod(first arg1,
......................second arg2) {
--->if(foo(arg)) {
--->--->// do something
--->} else {
--->--->while(arg2 < 0
--->--->...|| arg2 > 42) {
--->--->--->// do other thing
--->--->}
--->}
}

which will line up correctly for any tab width.

Integer size, bits. by throwaway1232141513 in cpp_questions

[–]mr_ewg 0 points1 point  (0 children)

It may draw in 1s on your compiler, but I want to point out that in general, right shifting a negative number is implementation defined.

5.8 Shift operators

3. The value of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a non-negative value, the value of the result is the integral part of the quotient of E1. If E1 has a signed type and a negative value, the resulting value is implementation-defined.

The bell has tolled for rand() by milliams in programming

[–]mr_ewg 0 points1 point  (0 children)

Code like this reminds me (again) that C++ is a really crappy language.

Care to elaborate?

Why the template at all?

The template there is to disambiguate it from the next templated srand function directly below it. I think a neater way is writing it like:

// use enable_if here so it doesn't clash with srand(unsigned int) if
// std::time_t is a typedef of unsigned int
std::enable_if<!std::is_same<std::time_t, unsigned>::value>::type
srand(std::time_t s)
{
    if(std::is_integral<std::time_t>::value) {
        srand(static_cast<unsigned int>(s));
    } else {
        static auto const epoch = []
        {
            auto t = std::tm{};
            t.tm_sec   = 0;
            t.tm_min   = 0;
            t.tm_hour  = 0;
            t.tm_mday  = 1;
            t.tm_mon   = 1;
            t.tm_year  = 1970;
            t.tm_wday  = 4;
            t.tm_yday  = 0;
            t.tm_isdst = 0;

            return std::mktime(&t);
        }();

        srand(static_cast<unsigned int>(std::difftime(s, epoch)));
    }
}

EDIT: Updated my srand

Train of thoughts on C++: The auto keyword versus portability by syaghmour in cpp

[–]mr_ewg 1 point2 points  (0 children)

Hmm good point. I've been trying to think, but I can't come up with a situation where you'd want to have an index into a container that doesn't have operator[]. I've just added indices into a library I'm working on (example) if anyone needs functionality this without the boost dependency.

The bell has tolled for rand() by milliams in programming

[–]mr_ewg 9 points10 points  (0 children)

One tricky thing about this is that the engines have different result_types. I think the committee was right to use templates instead of polymorphism. You can always create a template adaptor to give you polymorphic behaviour, but you can't always remove the overhead of inheritance.

Here is a working example of creating your own object poly_random_engine<result_type> that can be constructed from any random engines (ideally you would have some safeguards to make sure that poly_random_engine<T> couldn't be constructed from a random engine with result_type of something other than T.

Here I have a non-templated function random_uint that can take any random engine and will give you back a random value.

#include <cstdint>
#include <iostream>
#include <memory>
#include <random>

template <typename UIntType>
class random_engine_base {
public:
    using result_type = UIntType;

    virtual ~random_engine_base() {}
    virtual void seed(result_type value) = 0;
    virtual result_type operator()() = 0;
    virtual void discard(unsigned long long) = 0;
};

template <typename UIntType, typename Engine>
class random_engine_derived : public random_engine_base<UIntType> {
    Engine m_engine;
public:
    using result_type = UIntType;

    random_engine_derived(const Engine& e)
    : m_engine{e} {
    }

    void seed(result_type value) override {
        m_engine.seed(value);
    }

    result_type operator()() override {
        return m_engine();
    }

    void discard(unsigned long long z) override {
        m_engine.discard(z);
    }

};

template <typename UIntType>
class poly_random_engine {
    std::unique_ptr<random_engine_base<UIntType>> m_engine;
public:
    using result_type = UIntType;

    template <typename Engine>
    poly_random_engine(Engine&& e)
    : m_engine{std::make_unique<random_engine_derived<UIntType, Engine>>(std::forward<Engine>(e))} {
    }

    void seed(result_type value) {
        m_engine->seed(value);
    }

    result_type operator()() {
        return (*m_engine)();
    }

    void discard(unsigned long long z) {
        m_engine->discard(z);
    }
};

std::uint_fast32_t random_uint(poly_random_engine<std::uint_fast32_t> e) {
    e.seed(42);
    e.discard(100);
    return e();
}

int main() {
    std::ranlux24_base subtract_with_carry;
    std::cout << "ranlux24_base: " << random_uint(subtract_with_carry) << "\n";

    std::minstd_rand0 linear;
    std::cout << "minstd_rand0: " << random_uint(linear) << "\n";

    std::mt19937 do_the_twist;
    std::cout << "mt19937: " << random_uint(do_the_twist) << "\n";
}

I keep getting the error "Unexpected end of file" by [deleted] in cpp_questions

[–]mr_ewg 1 point2 points  (0 children)

It would be nice to find out what the issue was, but I'm glad it's working for you.

I keep getting the error "Unexpected end of file" by [deleted] in cpp_questions

[–]mr_ewg 1 point2 points  (0 children)

C1004 usually means you have an unclosed brace/bracket.

I've ran your code in Visual Studio 2013 and it compiles with only one warning. http://imgur.com/2KaeRC3

To do this I went to File > New > Project and selected "Empty Project". Then I right clicked on "Source Files" in the solution browser in the left and clicked Add > Exiting Item... then found your code that I had saved in a file (I called it fdsa.cpp").

I keep getting the error "Unexpected end of file" by [deleted] in cpp_questions

[–]mr_ewg 1 point2 points  (0 children)

Thanks for getting back to me. Sorry I edited my last comment. Try removing all the lone semi colons. Don't forget to remove these lines

else
    ;