22 Şubat 2019 Cuma

Pointer To Array

Giriş
Array'e pointer elde etmek için
array
&array
&array[0]
kullanılabilir.

Görsel olarak şöyledir.
+----------+----------+----------+----------+----------+
| array[0] | array[1] | array[2] | array[3] | array[4] |
+----------+----------+----------+----------+----------+
^
|
&array[0]
|
&array
Örnek
Şöyle yaparız. p pointer to array ve daha sonra istesek başka bir yere de point ettirebiliriz.
int a[5] = {1,2,3,4,5}
int * p = a;
Örnek
Şöyle yaparız.
int array[5] = { 10,11,12,13,14};

std::cout << array << std::endl;
std::cout << &array << std::endl;
std::cout << &array[0] << std::endl;
Örnek
Şu ise derlenmez.
int a[5] = {1,2,3,4,5};
int*& ref = a;
Açıklaması şöyle
a is not a pointer, it is an array. It has the type int[5]. What it can do it is decay to a pointer int*, which is what happens in the first case. So, taking a reference to p is ok.

Now for the second case. Remember that a is not a pointer. So, there is an implicit conversion happening from int[5] to int*. The result of that conversion is a prvalue. But you can't bind a non-const lvalue reference (which is what ref is) to an rvalue! So the code fails to compile.
Örnek
Pointer To Array'in adresini almak. Elimizde şöyle bir kod olsun.
int *pArray = new int[5];

std::cout << pArray << std::endl; //İlk elemanın adresi
std::cout << &pArray << std::endl; //Pointer'ın adresi
std::cout << &pArray[0] << std::endl;//İlk elemanın adresi
Görsel olarak şöyledir.
+--------+       +-----------+-----------+-----------+-----------+-----------+-----+
| pArray | ----> | pArray[0] | pArray[1] | pArray[2] | pArray[3] | pArray[4] | ... |
+--------+       +-----------+-----------+-----------+-----------+-----------+-----+
^                ^
|                |
&pArray          &pArray[0]

21 Şubat 2019 Perşembe

std::add_lvalue_reference

Bu metodun ne işe yaradığını anlamadım. İlk gördüğüm yer burası

Reference Collapsing

Giriş
const T& şeklindeki parametre kullanan template kod, eğer <int&> şeklinde çağrılırsa parametrenin const olmaması anlamına gelir.

Kodu her zaman şöyle çağırmak gerekir.
g<int>(n);
// or just
g(n);
Şu şekildeki çağrılar yanlış
 int n{};
g<int&>(n);
Açıklaması şöyle.
...so you have specified that T is a int&. When we apply a reference to an lvalue reference, the two references collapse to a single one, so int& & becomes just int&. Then we get to the rule from [dcl.ref]/1, which states that if you apply const to a reference it is discarded, so int& const just becomes int&...
Örnek
Elimizde şöyle bir kod olsun.
template<typename T>
void f(T a, const T& b)
{
  ++a; // ok
  ++b; // also ok!
}

template<typename T>
void g(T n)
{
  f<T>(n, n);
}

int main()
{
  int n{};
  g<int&>(n);
}

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.