29 Haziran 2018 Cuma

std::basic_stringbuf

Giriş
Bu sınıf tüm streamlerin (örneğin std::basic_stringstream) içinde bulunur.

str metodu
Örnek ver

28 Haziran 2018 Perşembe

std::atomic_flag

Giriş
C++'ta atomic bool olarak kullanılabilecek iki sınıf var. Bunlar std::atomic_bool ve std::atomic_flag

Constructor
Bu sınıf contructor metoduna sahip olmasına rağmen değeri belirsiz olarak başlıyor. ATOMIC_FLAG_INIT ile ilklendirilebiliir.
Örnek
Şöyle yaparız.
std::atomic_flag lck = ATOMIC_FLAG_INIT;
clear metodu
Bayrağı bırakmak için şöyle yaparız
lck.clear();
test_and_set metodu
Bayrağı test etmek için şöyle yaparız
while (lck.test_and_set()) {...}

27 Haziran 2018 Çarşamba

std::future

Giriş
İki çeşit future nesnesi var. Bunlar std::future ve std::shared_future. Eskiden std::future sınıfı std::unique_future olarak adlandırılmıştı. Ancak artık sadece std::future olarak değişti.

std::future dönen sonucu saklamak için bellek alanı yaratır. Bu sınıf MoveConstructable olarak düşünülebilir. Bu yüzden sonuç bir kere alınabilir.

Continuation
C++11 Continuation için destek sağlamıyor. boost::future bu desteği sağlıyor. Şöyle yaparız.
boost::future<void> f1 = boost::async(...);
boost::future<void> f2 = f1.then(...);
boost::future<void> f3 = f2.then(...);
...
Bir gün then() metodunun da standarda girmesini ümit ediyorum.


constructor - std::async
Şöyle yaparız.
std::future<int> x = std::async(()-> return 42;);
constructor - std::promise
Örnek ver.

get metodu
std::future nesnesinin get() metodu bir değer döndürse bile, thread'in bittiği anlamına gelmez. thread detached değilse join ile beklemek gerekir.
void
set_string(std::promise<std::string>& p)
{
  p.set_value("set from thread");
}

int
main()
{
  std::promise<std::string> p;
  std::future<std::string> f = p.get_future();
  std::thread t(&set_string, std::ref(p));
  std::cout << f.get() << std::endl;
  t.join();
}
then metodu
Açıklaması şöyle.
Attach the continuation func to *this. The behavior is undefined if *this has no associated shared state (i.e., valid() == false).
...
After this function returns, valid() is false.
Şöyle yaparız.
auto f0 = std::async([]{return 0;});
auto f1 = f0.then([](auto& f){ return f.get() + 10; });
valid metodu
Nesneye bir değer atanıp atanmadığını döner. Şöyle yaparız.
std::future<int> f;

if (some_condition)
  f = std::async(...);
...
int x = f.valid() ? f.get() : 0;
wait_for metodu
Sonuç olarak std::future_status::ready,std::future_status::timeout dönebilir
Örnek
Şöyle yaparız.
td::future<int> future = std::async(std::launch::async, [](){ 
    veryslow();
});

std::future_status status;

status = future.wait_for(std::chrono::milliseconds(100));

if (status == std::future_status::timeout) {
    // verySlow() is not complete.
} else if (status == std::future_status::ready) {
    // verySlow() is complete.
    // Get result from future (if there's a need)
    auto ret = future.get();
}
Örnek
Şöyle yaparız.
using namespace std::chrono_literals;
auto future = std::async(std::launch::async, &Component::recv, handler);
if(future.wait_for(500ms) == std::future_status::timeout) {
   // timed out
}
Örnek
Eğer süre olarak eksi bir değer verirsek beklemeden future nesnesinin hazır olup olmadığını döner. Şöyle yaparız.
template<typename R>
bool isReady(std::future<R> const& f)
{
  ...
  return f.wait_for(std::chrono::seconds(-1)) == std::future_status::ready;
}



std::lower_bound - Büyük Eşittir (>=) Araması

Giriş
Şu satırı dahil ederiz.
#include <algorithm>
İmzası şöyle. Value veya value + comparator ile çalışabilir.
template<class ForwardIterator, class T>
ForwardIterator
lower_bound(ForwardIterator first, ForwardIterator last,const T& value);

template<class ForwardIterator, class T, class Compare>
ForwardIterator
lower_bound(ForwardIterator first, ForwardIterator last,const T& value, Compare comp);
Açıklaması şöyle. Yani comparator false dönmediği müddetçe aramaya devam eder.
The furthermost iterator i in the range [first, last] such that for every iterator j in the range [first, i) the following corresponding conditions hold: comp(*j, value) != false.
std::map için Kullanmayın
std::map sınıfının kendi lower_bound() metodu vardır

Dizinin Sıralı Olması
Dizinin sıralı olması gerekir diye biliyordum ancak daha sonra sıralı olmak zorunlululuğu olmadığını öğrendim. Dolayısıyla lower_bound sıralı bir diziye yeni eleman eklemek için kullanılabilir.
Returns an iterator pointing to the first element that is not less than key.
Algoritma belirtilen değer ile iterator'ün değerini şöyle karşılaştırır.
if (*it < value) { ... }
Value ile kullanımı - ilk >= koşulu
Küçükten büyüğe sıralı dizilerde kullanılır. Verilen değerden ">=" olan ilk değeri döndürür. Küçükten büyüğe boy sıralamasında benden bır tık daha uzun veya benimle aynı uzunluktaki ilk kişinin konumunu verir.

Value ile kullanımı - ilk <= koşulu
Büyükten küçüğe sıralı dizilerde kullanılır. Verilen değerden "<=" olan ilk değeri döndürür. Büyükten küçüğe boy sıralamasında benden bır tık daha kısa veya benimle aynı uzunluktaki ilk kişinin konumunu verir.

Örnek
Dolayısıyla arama için kullanılan değerin < operatörünün tanımlı olması gerekir. Elimizde MyInt isimli bir sınıf olsun. Aşağıdaki kodda lower_bound MyInt() için < 2 operatörünü arayacak ve bulacak. Dolayısıyla kod derlenir
#include <set>
#include <algorithm>

using namespace std;

class MyInt {
  public:
    MyInt(int _val): {...}
    bool operator<(const MyInt& other) const {...}
};

set<MyInt> s;
s.insert(1);
s.insert(MyInt(2));
s.insert(3);
set<MyInt>::iterator it = lower_bound(s.begin(), s.end(), 2);
Örnek
Bu bir HackerRank sorusu. Büüykten küçüğe puanlar olsun. Alice'in en üstten kaçıncı olduğunu bulmak için şöyle yaparız. sort() ve lower_bound() çağrılarından büyükten küçüğe sıralama kullanılıyor.
std::vector<int> scores { 100, 100, 50, 40, 40, 20, 10 };
std::vector<int> aliceScores { 5, 25, 50, 120 };
// sort and erase duplicates
std::sort(std::begin(scores), std::end(scores), std::greater<int>());
scores.erase(std::unique(std::begin(scores), std::end(scores)), std::end(scores));

// just a lambda to make the output part more readable
auto locateRanking = [](const auto& _scores, int _newScore){
  auto itr = std::lower_bound(std::begin(_scores), std::end(_scores), _newScore,
    std::greater<int>());
  return std::distance(std::begin(_scores), itr) + 1;
};

// output part
for (auto newScore : aliceScores)
{
  std::cout << locateRanking(scores, newScore) << std::endl;
}
Value + Compartor ile Kullanımı
Örnek
Elimizde şöyle bir kod olsun
const std::vector<int> v{1, 3, 4, 2, 7, 5, 8, 6};
Şöyle yaparız.
auto pred2 = [](int lhs, int rhs){ return (lhs < 5) > (rhs < 5); }
assert(std::is_sorted(v.begin, v.end(), pred2));
auto it2 = std::lower_bound(v.begin, v.end(), 5, pred2);

assert(it1 == it2); // *it1 == 7
Bazı notlar
1. Eğer aranılan değer yoksa, alt sınır için değerden büyük olan ilk elemandan bir önceki konumu döndürür. Bu konum mesela begin () olabilir.

2. Eğer aranılan değer varsa veya bir kaç tane varsa, alt sınır için değerden bir önceki konumu döndürür. 

3. Eğer aranılan değer yoksa, ve tüm değerler aranılandan küçükse, end() döner.

Bu method Java'daki NavigableSet.ceiling() metoduna benziyor. Ancak Java'da verilen iterator aralığının sıralı olması gerekmez.

binary_find metodu
lower_bound binary_find isimli yeni bir metod yazmak için kullanılabilir. Aranan değer varsa iterator değeri döner, yoksa end değerini döner. Böylece STL ile gelen ve sadece boolean dönen binary_search algoritmasının sınırlamasından kurtuluruz.
template<class Iter, class T>
Iter binary_find(Iter begin, Iter end, T val)
{
    // Finds the lower bound in at most log(last - first) + 1 comparisons
    Iter i = std::lower_bound(begin, end, val);

    if (i != end && !(val < *i))
        return i; // found
    else
        return end; // not found
}