31 Aralık 2020 Perşembe

wchar_t Tipi

Giriş
Büyüklüğü çoğunlukla 2 byte. Bazı sistemlerde ise 4 byte. Açıklaması şöyle
... since wchar_t is usually 2 bytes in size it can be used to represent text in any 2-byte encoding. It can also be used for representing text in variable-width multi-byte encodings of which the most common is UTF-16.
wchart_t kullanan bazı metodlar şöyle

wprintf metodu

Giriş
Bu metodu kullansak bile setlocale() çağrısını gerekir. Açıklaması şöyle
Because conversion of wide characters is done according to the currently set locale. By default a C program always starts with a "C" locale which only supports ASCII characters.
Örnek
Şu kod doğru çalışmaz
Doğru kod şöyle

28 Aralık 2020 Pazartesi

Integral Literals

Single Quote İle Okumayı Kolaylaştırmak
C++14'ten itibaren sayıları okumayı kolaylaştırmak için apostrof kullanılabilir.
Örnek
Şöyle yaparız.
int LargeNumber = 1'000'000;
Şöyle yaparız.
int i = 1'000'000'000;
C++ ve C# gibi dillerde short için literal eki mevcut değil. En küçük literal eki int.

Eğer integral sayılar için literal eki kullanılmazsa, int'ten küçük olmamak kaydıyla derleyici sayının sığdığı en küçük int tipi seçer. Örneğin long gibi. Şimdi literal eklerinin detaylarına bakalım.

Integer Literal
Bir öneriyle yeni integer literal ön ekleri teklif edildi. Teklif şöyle

1 int
Bir ek koymaya gerek yok.
auto a = 4 ; // int
2 unsinged int - U eki
Şöyle yaparız.
auto b = 4U ; // unsigned int
3 long int - L eki
Şöyle yaparız.
auto c = 4L ; // long int
4 unsigned long int - UL eki veya LU
Örnek
Şöyle yaparız.
auto foo = 12ul;
Örnek
Şöyle yaparız.
75         // int
75u        // unsigned int
75l        // long
75ul       // unsigned long 
75lu       // unsigned long

3.14159L   // long double
6.02e23f   // float  
5 unsigned long long - ULL
en az 64 bit olan unsigned long long.
Örnek - Atama
Şöyle yaparız.
uint64_t x = 1000000000ull;
Örnek - Bit Shit
Bit kaydırma işlemlerinde şöyle yapmak gerekir.
uint64_t x2 = (1ull << 35ull);
Aynı sonucu şöyle de elde edebiliriz.
auto x = std::uint64_t(1) << 35;
Ayrıca stdint.h dosyasında tanımlı olan UINT64_C macrosu da kullanılabilir.

Örnek - Çarpma
Şöyle yaparız. İlk satırda en baştaki sabitin LL olması yeterli. LL tipi çarpı int tip her zaman LL tipinden çıktı verir
long long int n = 2000LL*2000*2000*2000;
long long int n = 2000LL*2000LL*2000LL*2000LL;

6 float - f
Şöyle yaparız
6.02e23f   // float
int_64_t
Aslında bu bir user defined literal ancak yine de not almak istedim
Örnek
Şöyle yaparız
constexpr std::int64_t operator "" _int64(unsigned long long v)
{ return static_cast<std::int64_t>(v); }

std::equal metodu

Örnek
Şöyle yaparız.
static bool isPalindrome(const std::string& str)
{
  return std::equal(str.begin(), str.end(), str.rbegin());
}
Örnek
Bir düzden bir tersten sıralı iki diziyi karşılaştırmak için şöyle yaparız
int array1[] = {1,2,3,4,5};
int array2[] = {5,4,3,2,1};
std::equal(std::begin(array1), std::end(array1), std::rbegin(array2))

Generics ve Upper Bound

Giriş
C++ dilinde, Java'daki gibi template/generic tiplere "Upper Bound" verme imkanı yok.
 Belki yapmak ta gerekmiyor. Ancak illa ki benzer bir maktık kullanmak istersek önümüzde bir kaç seçene var

1. static_assert + std::is_base_of_v
Örnek
Şöyle yaparız
template<class T> class MyClass{
  static_assert(std::is_base_of_v<Draw_Shape,T>);
};
2. std::enable_if_t ile SFINAE
Açıklaması şöyle
note that the =true does not compare the test to the value true. It is not ==true. What is going on here is ridiculously complex and annoying; using SFINAE for this purpose is a hack, and this is just a monkey-see monkey-do way to make it clean.
Şöyle yaparız. Buradaki std::enable_if_t<...> = true kullanımı, normal kullanımdan biraz daha farklı. Normal kullanım için std::enable_if_t Alias'ı yazısına bakabilirsiniz.
template<class T,
  std::enable_if_t<std::is_base_of_v<Draw_Shape,T>, bool> =true
>
class MyClass{
};
3. C++20 concepts
Örnek - std::is_base_of_v
Şöyle yaparız
template<class T> requires std::is_base_of_v<Draw_Shape,T>
class MyClass{
};
Örnek - std::is_derived_from
std::is_derived_from yazısına taşıdım

std:::is_constant_evaluated

Örnek
Açıklaması şöyle
There are 3 kinds of functions in C++, and is_constant_evaluated only makes sense in one of them.
Şöyle yaparız
// a strictly run-time function
int foo(int arg) 
{
    if (std::is_constant_evaluated()) // pointless: always false
        // ...
}

// a strictly compile time function
consteval int foo(int arg) 
{
    if (std::is_constant_evaluated())  // pointless: always true
        // ...
}

// both run-time and compile-time
constexpr int foo(int arg) 
{
    if (std::is_constant_evaluated())  // ok: depends on context in 
                                       // which `foo` is evaluated
        // ...
}

24 Aralık 2020 Perşembe

ranges Views

Giriş
Açıklaması şöyle
A View is something that you apply on a range and performs some operation. A view does not own data and it's time to copy, move, assignment is constant.
Çoğu view için alternatif bir isim de var. Açıklaması şöyle
In general, you can use a view such as std::views::transform with the alternative name std::transform_view.
Alternatif isimler parametre olarak bir container/view alıyorlar. view olanlar ise "pipe" işareti ile kullanılıyorlar.

Örnek
Şöyle yaparız İlk kullanımda pipe işareti görülebilir. İkinci kullanımda ise parametre olarak pi container değişkeni geçiliyor.
auto print = [](char x) { std::cout << x; };
int main() { constexpr char pi[] { '3', '.', '1', '4', '1', '5', '9', '2', '6', '5' }; std::ranges::for_each(pi | std::ranges::views::take(8), print); std::cout << '\n'; std::ranges::for_each(std::ranges::take_view{pi, 8}, print); std::cout << '\n'; }
Çıktı olarak şunu alırız
3.141592
3.141592
Örnek
Şöyle yaparız. Burada alternatif isimler kullanıldığı için parametre olarak bir container/view geçiliyor.
const std::string s{"cosmos"};
 
const std::ranges::take_view tv{s, 3};
const std::ranges::ref_view rv{tv};
 
std::cout
  << std::boolalpha
  << "call empty() : " << rv.empty() << '\n'
  << "call size()  : " << rv.size() << '\n'
  << "call begin() : " << *rv.begin() << '\n'
  << "call end()   : " << *(rv.end()-1) << '\n'
  << "call data()  : " << rv.data() << '\n'
  << "call base()  : " << rv.base().size() << '\n' // ~> tv.size()
  << "range-for    : ";
 
for (const auto c: rv) { 
  std::cout << c; 
}
std::cout << '\n';
Çıktı olarak şunu alırız
call empty() : false
call size()  : 3
call begin() : c
call end()   : s
call data()  : cosmos
call base()  : 3
range-for    : cos

std::ranges::views::all - takes all elements
Alternatif : std::ranges::all_view
Örnek ver

std::ranges::views::chunk - C++23 ile geliyor
Örnek
Vector'deki yan yana elemanları pair haline getirmek için şöyle yaparız
#include <iostream>
#include <ranges>
#include <vector>

int main()
{
  std::vector<int> values = {1,2,3,4,5,6,7,8,9,10};
  auto chunk_to_pair = [](auto chunk)
  {
    return std::pair(*chunk.begin(), *std::next(chunk.begin()));
  };
  for (auto [first, second] : values | std::ranges::views::chunk(2)
    | std::ranges::views::transform(chunk_to_pair))
  {
    std::cout << first << second << std::endl;
  }
}
Aynı şeyi std::ranges::views::stride ile şöyle yaparız
#include <iostream>
#include <ranges>
#include <vector>

int main()
{
  std::vector<int> values = {1,2,3,4,5,6,7,8,9,10};
  auto odds = values | std::ranges::views::drop(0) | std::ranges::views::stride(2);
  auto evens = values | std::ranges::views::drop(1) | std::ranges::views::stride(2);
  for (auto [first, second] : std::ranges::views::zip(odds, evens))
  {
    std::cout << first << second << std::endl;
  }
}
std::ranges::ref_view - takes all elements of another view
Alternatif : Yok
Örnek ver

std::ranges::istream_view - applies operator>> on the view
Alternatif : std::ranges::basic_istream_view
Örnek ver

std::ranges::views::common - converts a view into a std::common_range
Alternatif : std::ranges::common_view
Örnek ver

std::ranges::views::drop - skips the first N elements of another view
Alternatif : std::ranges::drop_view
Örnek ver

std::ranges::views::drop_while - skips the initial elements of another view until the predicate returns false
Alternatif :std::ranges::drop_while_view
Örnek ver

std::ranges::views::elements - creates a view on the N-th element of tuples
Alternatif : std::ranges::elements_view
Örnek ver

std::ranges::views::filter - takes the elements which satisfies the predicate
Alternatif : std::ranges::filter_view
Örnek ver

std::ranges::views::join - joins a view of ranges
Alternatif : std::ranges::join_view
Örnek ver

std::ranges::views::keys - creates a view on the first element of a pair-like values
Alternatif : std::ranges::keys_view
Örnek ver

std::ranges::views::reverse - iterates in reverse order
Alternatif : std::reverse_view
Örnek ver

std::ranges::views::split - splits a view by using a delimiter
Alternatif : std::ranges::split_view
Örnek ver

std::ranges::views::take - takes the first N elements of another view
Alternatif : std::ranges::take_view
Örnek ver

std::ranges::views::take_while - takes the elements of another view as long as the predicate returns true
Alternatif : std::ranges::take_while_view
Örnek ver

std::ranges::views::transform - transforms each element
Alternatif : std::ranges::transform_view
Örnek ver

std::ranges::views::values - creates a view on the second elements of a pair-like values
Alternatif : std::ranges::values_view
Örnek ver