ZWI #4 – jak wylosować elementy bez powtórzeń

Losowanie bez powtórzeń jest chyba jednym z najczęstszych zadań dla początkujących, zarówno uczących się samodzielnie, jak i na studiach. Często przejawia się w zadaniu typu “utwórz program losujący liczby w Lotto”. Równie często spotykam kod z wydajnością O(evil), którego powstydziłbym się nawet w najbezczelniejszym Lawful Evil – mieszanina randów, srandów, sprawdzania w pętli O(n3) czy wartość jest już znaleziona, alokacji pamięci za pomocą new[] itd.

Jest to w dużej mierze pokłosie sposobu nauczania C++. W tym poście przedstawię proste, czytelne i wydajne sposoby uzyskania tego samego efektu.

ZWI#3 – jak wywołać specjalizację szablonu funkcji dla wszystkich typów z listy

Tym razem podzielę się pytaniem jakie otrzymałem na IRC-u:

<cauchy> mam sobie funkcyjke z templejtem
<cauchy> i chce sobie ta fn wywolac dla jakiejs tam listy typow
<cauchy> np dla int, in64_t, string, vector<int>, vector<string>, itd
<cauchy> jakos fajnie daloby sie to zrobic w petli zebym nie musial explicitnie dawac po kolei
<cauchy> fn<int>();
<cauchy> fn<string>();
<cauchy> …

Oczywiście, że by się dało!

ZWI #2 – zaprzyjaźniona pojedyńcza specjalizacja szablonu

Do napisania tej notki zainspirowało mnie to pytanie na forum. Lekko parafrazując podany kod, szablon klasy wyglądał następująco:

template<typename T>
void bar(Foo<T> f)
{
    DBG(f.val);
}
 
template<typename T>
struct Foo
{
    Foo(T val) : val{val} {}
 
    template<typename U>
    friend void bar(Foo<U>);
 
private:
    T val;
};

ZWI #1: Jak wykryć kontenery asocjacyjne w czasie kompilacji

Tym postem rozpoczynam kolejną serię – ZWI (Zapytane w Internecie). W planach jest co najmniej jeden wpis ;​) Posty będą przedstawiały pytania, na które odpowiedziałem na różnej maści forach, które (lub których odpowiedzi) uznałem za godne uwagi.

Na pierwszy ogień idzie następujące pytanie z forum 4programmers:

Mam prostą funkcję

template <typename Container, typename Value>
bool contains(const Container& container, const Value& value)
{
    return std::find(std::begin(container), std::end(container), value)
        != std::end(container);
}

Dla kontenerów asocjacyjnych (set, multiset, unordered_set, map itd.) można wykorzystać metodę find(), która jest szybsza niż globalne find(). Pytanie czy da się w prosty i elegancki sposób wykryć taką sytuację, żeby wywołać container.find(), bo nie uśmiecha mi się pisać specjalizacji dla każdego typu kontenera.