4 Şubat 2019 Pazartesi

constexpr

Metodu Sonucu Tanımlama
constexpr Döndüren Metod yazısına taşıdım.

const Alan vs constexpr Alan
constexpr Alan derleme zamanı değer alır ve bir daha değiştirilemez. Ancak const alan runtime'da değer alır ve arık bundan sonra değiştirilemz. Bu yüzden bazı template metodlar const değişken ile derlenemezler. Şu kod derlenmez
const size_t n = 3;
Eigen::Matrix<double, n, n> A;
Şöyle yaparız
constexpr size_t n = 3;
Eigen::Matrix<double, n, n> A;
Eigen::Matrix<double, n, n> B;
1. Alan Tanımlama
Şöyle yaparız.
constexpr const char foo[] = "blee";
Şöyle yaparız.
constexpr double some_double = 1.0;
1.1 Alan Tanımla - String Literal
Şu kod uyarı verir. Çünkü constexpr char* sadece  constant pointer to a non-const char anlamına gelir.
// warning: ISO C++ forbids converting a string constant to ‘char*’    
static constexpr char* name_ = "A";       
Şöyle yaparız. Bu kod constant pointer to a constant char anlamına gelir.
static constexpr const char* name_ = "A";    
2. Static Alan Tanımlama
Şöyle yaparız.
constexpr static int x{20};
Eğer istenirse static bir alana referans bile alınabilir. Şöyle yaparız.
constexpr static int x{20};
constexpr const int& z = x;
3. Static Üye Tanımlama
C++17 ile şöyle yaparız.
class Foo
{
  public:
    constexpr static std::tuple<int, unsigned int, unsigned short> table[3]
    = {std::make_tuple(1, 2, 3),
        std::make_tuple(4, 5, 6),
        std::make_tuple(7, 8, 9)};
};
C++11 derleyicisinde şu satırı eklemek te gerekir.
constexpr std::tuple<int, unsigned int, unsigned short> Table_class::table[3];
En Eski Yöntem
Eski C++ ile integral olmayan static const değişkenleri sınıfın özelliği gibi tanımlamak mümkün değildi. Bu yüzden aşağıdaki gibi yapmak gerekiyordu.
//my_class.hpp
private:
static const double some_double;

//my_class.cpp
const double my_class::some_double = 1.0;

Diğer Notlar
1. Trivial Destructor'a Sahip Olmayan Şeyler constexpr Olamaz
Örnek'teki kod derlenmez!
constexpr const std::string foo = "blee";
2. constexpr'nin Sağ Tarafı da constexpr olabilir.
Bazı basit örnekler şöyle
static constexpr int arr[] = {1,2,3,4,5,6};
constexpr const int *first = arr;
constexpr const int *second = first + 1; // would fail if first wasn't constexpr
constexpr int i = *second;
Eğer constexpr'nin sağ tarafında kullanılan değişken de constexpr değilse derleme hatası alırız.
struct S {
    constexpr int f() const { return 1; }  
};

int main() {
    static constexpr S s{};
    const S *sp = &s;
    constexpr int i = sp->f(); // error: sp not a constant expression
}

4. if constexpr
if constexpr yazısına taşıdım.

std::lock_guard Sınıfı

Giriş
lock_guard çok basit bir arayüz sunuyor.

Constructor
Kullanımı şöyle. İçine bir mutex veriyoruz. Scope içinde mutex kilitlenir. Çıkarken bırakılır. lock_guard template ile çalıştığı için mutex yerine lock() metodu veren herhangi bir sınıf ile de çalışırdı.
void member_foo() {
  std::lock_guard<mutex_type> lock(this->my_mutex);
  ...
}
Eğer mutex yerine başka bir tip vermek istersek BasicLockable olmalıdır. Dolayısıyla şu kod derlenmez.
std::lock_guard<pthread_mutex_t> lock(...);
Diğer

1.Return Value Optimization (RVO)
Klasik kullanımı şöyledir
Some_resource var;
{
  std::lock_guard<std::mutex> lock(mut);
  var = shared_Var;
}
Ancak bu kod RVO'dan faydalanmamızı sağlamaz. Şöyle yaparız.
// use an immediately-invoked temporary lambda
Some_resource var {
  [&] {
    std::lock_guard<std::mutex> lock(mut);
    return shared_var;
  } () // parentheses for invoke
};

2.Effective Modern C++ Item 16: "Make const member functions thread safe" 
Şöyle.
class Widget {
public:    
  int magicValue() const
  {
    std::lock_guard<std::mutex> guard(m);  // lock m    
    if (cacheValid) return cachedValue;
    else {
      auto val1 = expensiveComputation1();
      auto val2 = expensiveComputation2();
      cachedValue = val1 + val2;
      cacheValid = true;
      return cachedValue;
    }
  }                                        // unlock m    
private:
  mutable std::mutex m;
  mutable int cachedValue;                 // no longer atomic
  mutable bool cacheValid{ false };        // no longer atomic
};

1 Şubat 2019 Cuma

std::remainder

Giriş
Açıklaması şöyle.
The IEEE floating-point remainder of the division operation x/y calculated by this function is exactly the value x - n*y, where the value n is the integral value nearest the exact value x/y. When |n-x/y| = 1/2 the value n is chosen to be even.
std::fmod ile Farkı 
Açıklaması şöyle
std::remainder() is like std::fmod() except that it rounds the internal quotient n to the nearest integer instead of towards zero to an integer.
Bu yüzden sonucun artı/eksi değeri ilk parametre olan x'ten farklı olabiliyor. Açıklaması şöyle.
In contrast to std::fmod(), the returned value is not guaranteed to have the same sign as x.
Örnek
Elimizde şöyle bir kod olsun.
std::remainder(+5.1, +3.0) = -0.9
std::remainder(-5.1, +3.0) = 0.9
Açıklaması şöyle.
So to take the example in the question, when x = +5.1 and y = +3.0 The nearest integral value to x/y (1.7) is 2. So n is 2. So the remainder will yield x - 2y which is 5.1 - 2 * 3.0 which is 5.1 - 6.0 which is -0.9.

But when x = -5.1 and y = +3.0 The nearest integral value to x/y (-1.7) is -2. So n is -2. So the remainder will yield x - 2y which is -5.1 - (-2) * 3.0 which is -5.1 + 6.0 which is +0.9

std::fmod - bölme sonucunda kalanı bulma

Giriş
Metodun imzası şöyle. x/y = z işleminde x bölünen, y bölen, z bölümdür. fmod z değerini değil kalanı verir.
#include <math.h>

double fmod(double x, double y);
float fmodf(float x, float y);
long double fmodl(long double x, long double y);
Açıklaması şöyle.
The floating-point remainder of the division operation x/y calculated by this function is exactly the value x - n*y, where n is x/y with its fractional part truncated.

The returned value has the same sign as x and is less than y in magnitude.
Bu yazıyla ilgili olarak std::modulus yazısına da bakılabilir.

Neden std::fmod Gerekir
Normalde "modulus operatorünün" sağ tarafına bir tam sayının gelmesi gerekir. Eğer gelmezse derleyici aşağıdaki gibi bir hata verir. Yani şu kod için
int main() {
  double x = 6.3;
  double y = 2;
  double z = x % y;
}
Şöyle bir hata alırız.
error: invalid operands of types 'double' and 'double' to binary 'operator%'
Bu durumda fmod metodunu kullamak gerekir. "Modulus operatöründen" farklı olarak double bir değer döndürüyor.

Örnek
Elimizde şöyle bir kod olsun.
std::fmod(+5.1, +3.0) = 2.1
Açıklaması şöyle.
when x = +5.1 and y = +3.0,  x/y (5.1/3.0 = 1.7) with its fractional part truncated is 1. So n is 1. So the fmod will yield x - 1*y which is 5.1 - 1 * 3.0 which is 5.1 - 3.0 which is 2.1.
Örnek
Şöyle yaparız.
double a=fmod(4.1,1.0);
cerr<<std::setprecision(0)<<a<<"\n";
cerr<<std::setprecision(10)<<a<<"\n";
cerr<<std::setprecision(20)<<a<<"\n";
Çıktı olarak şunu alırız.
0.1
0.1
0.099999999999999644729
Örnek
Şöyle yaparız.
cout << "fmod of 5.3 / 2.0 is " << fmod (5.3,2) << endl;
Eksi Sonuç
fmod eksi sayı verebilir. Örneğin fmod (-3,4) = -3 verir. Modulus operatörü de eksi bir sayı döndürebilir. Dolayısıyla modulus operatörü ile sayının eksi veya artık olmasına bakmadan tek/çift olduğunu kontrol etmek için aşağıdaki gibi yapılabilir.
public static boolean isOdd(int i) {
   return i % 2 != 0;
}