25 Haziran 2019 Salı

std::exchange metodu

Giriş
C++14 ile geliyor. İmzası şöyle
template< class T, class U = T >
T exchange( T& obj, U&& new_value );
Açıklaması şöyle
Replaces the value of obj with new_value and returns the old value of obj.
İçi şöyledir.
template<class T, class U = T>
T exchange(T& obj, U&& new_value)
{
  T old_value = std::move(obj);
  obj = std::forward<U>(new_value);
  return old_value;
}
Örnek
Bir if koşulunun tek bir kere çalışmasını istersek şöyle yaparız.
if (static bool do_once = true; std::exchange(do_once, false)){...}
std::exhange() kullanmak istemiyorsak şöyle yaparız.
if (static bool do_once = true; do_once) { // enter only once
  std::cout << "hello one-shot" << std::endl;
  // possibly much more code
  do_once = false;
}


24 Haziran 2019 Pazartesi

Variadic Template Unary Right Fold

Giriş
"Her bir eleman için belirtilen lambdayı çalıştır" gibi okumak gerekir.
Metodun imzasında ...,pack şeklinde kullanılır.

Kodda önce bir işlem, daha sonra bir operator ve ardından üç nokta gelir.

Variadic Template Unary Left Fold yazısına da göz atabilirsiniz.

Örnek
Şöyle yaparız. Burada yüm sonuçlar OR'lanarak boolen bir sonuç dünülüyor.
template<class T1, class... Ts>
constexpr bool is_one_of() noexcept {
  return (std::is_same_v<T1, Ts> || ...);
}
Örnek
Şöyle yaparız. Burada yüm sonuçlar OR'lanarak boolen bir sonuç dünülüyor.
template<auto... ts, class T>
constexpr bool
is_magical(const T& t) noexcept(noexcept(((t == ts) || ...))) {
    return ((t == ts) || ...);
}

// usage
if (is_magical<1, 3, 7, 42, 69, 5550123>(x))
Örnek
Belirtilen parametreleri vector'e eklemek için şöyle yaparız.
template<typename T, typename... Args>
void pack(std::vector<uint8_t> &buffer, Args... args) {
  (buffer << args << ...);
}
Çağırmak için şöyle yaparız.
std::vector<uint8_t> buffer;
pack((uint8_t)0xFF, (uint32_t)0x0A, buffer);
Örnek
Şöyle yaparız. update_max diye bir lambda tanımlanıyor. Her bir elemena için lambda çağrılıyor.
template<typename... T>
constexpr size_t max_sizeof(){
  size_t max=0;
  auto update_max = [&max](const size_t& size) {if (max<size) max=size; };
  (update_max(sizeof (T)), ...);
  return max;
}


static_assert(max_sizeof<int, char, double, short>() == 8);
static_assert(max_sizeof<char, float>() == sizeof(float));
static_assert(max_sizeof<int, char>() == 4);
Örnek
Şöyle yaparız. Başa fazladan bir boşluk koyar ama zaten sadece örnek olması için not aldım.
#include <iostream>
#include <string>

template <typename... Args>
void print(Args... args)
{
  std::string sep = " ";
  std::string end = "\n";
  ((std::cout << sep << args), ...);
}

int main()
{
  print(1, 2, 3);
}
Örnek
Vector dizisindeki her bir vectörün tüm eleman için bir metod çağırmak istersek şöyle yaparız.
template <typename F, typename... Vectors>
void for_all_vectors(F&& f, Vectors&&... vs)
{
    (std::for_each(std::forward<Vectors>(vs).begin(), 
                   std::forward<Vectors>(vs).end(), 
                   f), ...);
}
Elimizde A,B,C sınıfları olsun.
class Base { ... }
class DerivedA : public Base { ... }
class DerivedB : public Base { ... }
class DerivedC : public Base { ... }
 Kullanmak için şöyle yaparız.
std::vector<A> my_a;
std::vector<B> my_b;
std::vector<C> my_c;

for_all_vectors([](const auto& x){ something(x); }, my_a, my_b, my_c);