29 Eylül 2020 Salı

std::declval

Tanımı
Şuna benzer
template<class T>
typename std::add_rvalue_reference<T>::type declval() noexcept;
Açıklaması şöyle
In some contexts, we don’t have the objects available that we need to pass to an expression to evaluate it in decltype and similar functionalities. We might even not be able to create those objects at all, e.g. because their classes have only private or protected constructors.
...
For those cases, std::declval comes in handy. It is just a declared function template that returns an rvalue reference to whatever you pass to it. That way we don’t need to artificially declare a poorly named function to have something that we can use in our decltype argument: decltype(f(std::declval<int>()))

It comes especially handy if you are in a templated context and the value you want to obtain depends on a template parameter.
Örnek
Şöyle yaparız. Sanki C tipinden bir nesne varmış gibi davranır. Aslında C nesnesini normalde ilklendiremeyiz. Burada C nesnesini foo() metodunun döndürdüğü tip türünden (yani int) n değişkeni tanımlanır
struct C {
    C() = delete;
    int foo() { return 0; }
};


int main() {
    decltype(declval<C>().foo()) n = 1;
    cout << n << endl;
}

decltype Member Field İçin Kullanımı

Örnek
Şöyle yaparız
template<typename T>
constexpr auto has_public_foo(T const &t) -> decltype(t.foo, true) 
{
    return true;
}

constexpr auto has_public_foo(...) 
{
    return false;
}

static_assert(not has_public_foo(Bar{}), "Public members are bad practice");

28 Eylül 2020 Pazartesi

std::fmin metodu

Giriş
Açıklaması şöyle
std::min is defined in terms of an (a<b) comparison expression (cppreference), with (a<b) ? a : b as a possible implementation, unlike std::fmin which guarantees NaN propagation from either operand, among other things. (fmin originally came from the C math library, not a C++ template.)

std::min metodu

Giriş 
Metodun imzası şöyle
const T& min (const T& l, const T& r );
Açıklaması şöyle
std::min is defined in terms of an (a<b) comparison expression (cppreference), with (a<b) ? a : b as a possible implementationstinationPrefixes
Bu metodun const olmayan bir türevi yok!
template <typename T>
T& min(T& a, T& b);
Bu yüzden şu kod derlenmez.
std::min(x, y) += 1;
Gerçekleştirimi şöyle olabilir.
const T& min(const T& l, const T&r) {
  return l <= r ? l : r;
}
Şöyle olabilir.
const T& min(const T& l, const T& r) {
  return r < l ? r : l;
}
Örnek
T tipini belirtmek istersek şöyle yaparız. Belitmezsek, parametre tiplerinden çıkarım yapılır.
std::min<int>(fifoCount, 128);
Her iki parametrenin de aynı tip olması gerekir.

Örnek
volatile aynı const gibi bir qualifier'dır. Elimizde şöyle bir kod olsun.
volatile int i{100};
int j{200};
std::cout << std::min(i, j);
Parametre tipleri farklı olduğu için bu kod derlenmez çıktı olarak şunu alırız.
error: no matching function for call to ‘min(volatile int&, int&)’
Çünkü std::min her iki parametresinin de aynı tip olmasını ister. Şöyle yaparız.
std::min<volatile int>(i, j)
std::min - initializer_list
C++11 ile geliyor. İmzası şöyle
template <class T>
constexpr T min(initializer_list<T> t);
Karşılaştırma için T'nin < işlemini desteklemesi ve metod T döndürdüğü için T'nin CopyConstructable olması gerekir.
Requires: T is LessThanComparable and CopyConstructible and t.size() > 0.

Örnek - variadic template
T yapısının std::pair olduğunu varsayalım. Şöyle yaparız.
#include <algorithm>

template <typename ...Ts>
auto intersection(const Ts&... ps)
{
  return std::make_pair(std::max({ps.first...}), std::min({ps.second...}));
}

23 Eylül 2020 Çarşamba

calloc metodu

Giriş
Şu satırı dahil ederiz
#include <stdlib.h>
calloc standart C metodudur. Açıklaması şöyle.
The calloc() function allocates memory for an array of nmemb elements of size bytes each and returns a pointer to the allocated memory. The memory is set to zero. If nmemb or size is 0, then calloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().
calloc Kullanmak Neden İyi?
Açıklaması şöyle. Kirli bir bellek alanı alma ihtimaline karşı kullanılıyor.
Because after you've used the space and released it with free(), it might be allocated again. If you don't use calloc(), there's no guarantee that the memory will be zeroed on the second time it is used. (Calling free() does not zero the space.)
İmzası
Metodun imzası şöyle. Verilen  blok büyüklüğünden n tane yaratır
 void *calloc(size_t nmemb, size_t size);`
Örnek
İlk parametre size_t tipinde olduğu için teorik olarak en fazla SIZE_MAX büyüklüğnde değer alabilir. Şöyle yaparız.
calloc(SIZE_MAX, 2) != NULL;
Diğer
Metodun başındaki c harfi muhtemelen "clear" anlamına geliyor. Malloc ile aynıdır, sadece sıfır ile doldurulmuş bir hafıza döndürüyor. Yani şu kod her zaman true döner.
int* ptr = calloc(sizeof (*ptr));
bool b = *ptr == 0;  // always true
Aynı şeyi malloc ile yapmak isteseydik şöyle yapardık.
char* buffer = (char*)malloc(100);
memset(buffer,0,100);

21 Eylül 2020 Pazartesi

decltype Method Signature İçin Kullanımı

Metodun İmzasını Kontrol İçin
Şöyle yaparız. Aynı örneği static_assert yazısında da kullandım.
static_assert(std::is_same<decltype(c(0.0,0.0)), int>::value, 
"c must take two doubles and return int")
Metodun Varlığını Kontrol Etmek İçin
Örnek
Şöyle yaparızz
#include <iostream>
#include <vector>

template <typename T, typename = void>
struct has_begin : std::false_type {};

template <typename T>
struct has_begin<T,decltype(void(std::declval<T &>().begin()))> : std::true_type {};

int main(int argc, char *argv[])
{
    std::cout << has_begin<std::vector<int>>::value << std::endl;
}
Return Type Bulmak İçin
Bir metodun döndürdüğü tip şöyle bulunur.
typedef decltype(MyMethod(declval<MyType1>(),declval<MyType2>())) RetType;
Return Type Tanımlamak İçin
Template kodlarken return type bazen parametrelerde bağlı olabiliyor. Bu durumda decltype kullanılır.

Örnekte decltype a ve b'nin çarpımının tipi olarak kullanılmış
template<class A, class B>
void MultiplyAB(A a, B b, decltype(a*b)& output)
{
    output = a * b;
}
Eğer out parametresi yerine auto return type kullanırsak şöyle olur.
template<class A, class B>
auto MultiplyAB(A a, B b) -> decltype(a*b)
{
    return a * b;
}
Bazı örneklerde decltype sanki iki parametre alıyormuş gibi görünüyor. decltype iki parametre almaz. Sadece en son parametre return type tanımlamak için kullanılır. Diğer parametreler genelde bir koşulun doğruluğunu kontrol etmek için kullanılır.

Template kullansaydık, myClass sınıfının f metodu varsa (koşul) , void dön demek için şöyle yapardık.
template <typename T>
auto test(T &myclass) -> decltype(myclass.f(), void()) 
{
    // do something here, don't return anything (void)
}
Bir başka örnekte C sınıfının parametre almayan f metodu olup olmadığı kontrol ediliyor. f'nin döndürdüğü değer önemsiz.
template<class C, class F>
auto test(C c, F f) -> decltype((void)(c.*f)(), void()) { }