decltype etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
decltype etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

2 Kasım 2020 Pazartesi

decltype Template İçinde Placeholder Olarak Kullanımı

Örnek
Şöyle yaparız.
template <decltype(auto)>
struct X {};

int foo ;

int main() {
  X<(foo)> x;
  static_cast<void>(x);
}
Örnek
Şöyle yaparız
#include <type_traits>

template<decltype(auto) arg>
struct Foo {};

int main()
{
    constexpr int x = 42;
    static_assert(std::is_same_v<Foo<42>, Foo<x>>);
}

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()) { }



26 Mart 2020 Perşembe

decltype Pointer ile Kullanımı

Giriş
Bazı problemler şöyle
- Pointer'ın point ettiği nesnenin tipini bulmak
- Pointer'ın adresini bulmak

Örnek - Pointer'ın Point Ettiği Nesnenin Tipini Bulmak
1. Eğer değişken pointer ise, dereference veya std::decay ile kullanılabilir. Dereference ile kullanım şöyle olur. Şöyle yaparız. Burada amaç foo* tipini foo haline getirmek. Yani pointer'ın point ettiği nesnenin tipini bulmak. Burada decltype(*a) şeklide kullanılıyor.
#include <memory>

int main()
{
  int* a = new int(2);

  std::unique_ptr<std::decay<decltype(*a)>::type> p(a);
}
C++14 ile decay biraz daha kısaltılarak decay_t haline gelmiş. Böylece std::decay<>::type şeklinde yazmak zorunda kalmıyoruz.
#include <memory>

int main()
{
  int* a = new int(2);

  std::unique_ptr<std::decay_t<decltype(*a)>> p(a);
}
2. Ya da remove_reference_t kullanabiliriz. Şöyle bir kod olsun.
int a = 42;
int *p = &a;
Bu kodu remove_reference_t ile kullanabiliriz.
std::numeric_limits<
    std::remove_reference_t<decltype(*p)>
>::max();
Örnek - const Pointer
Entity Pointer'ın const olması decltype sonucunu const yapmaz.
struct A { double x; };
const A* a = new A();
decltype(a->x) x3; // type is double
Örnek - Pointer'ın Adresini Almak
Elimizde şöyle bir kod olsun. Bu kodlar pointer'ın adresini almaz. 
template <typename T>
struct Foo
{
    Foo(T arg) : ptr(arg) {}
    T ptr;
};

int main() 
{
    int* a = new int(6);
    Foo<decltype(a)> foo1(a); // ptr is a copy of a pointer
    Foo<decltype(&a)> foo1(&a); // ptr seems to be a pointer to a pointer
}
Şöyle yaparız
Foo<decltype(a) &> foo1(a).
veya şöyle yaparız
#include <functional>

template <typename T>
struct Foo
{
  Foo(T arg) : ptr(arg)
  {
  }
  T ptr;
};

int main()
{
  int* a = new int(6);

  Foo<std::reference_wrapper<int*>> foo1(std::ref(a));
  foo1.ptr[0] = 1;  // ok

  // This also works
  int* b = new int(6);
  Foo<std::reference_wrapper<decltype(b)>> foo2(std::ref(b));
  // and this too
  foo1 = foo2;

  // Or, if you use c++17, even this
  Foo foo3(std::ref(b));
}
Örnek - Pointer'ın Kaç Seviye Olduğunu Bulmak
Şöyle yaparız. Burada decltype<(T&)>() şeklide kullanılıyor. Pointer'ın adresi
template <class T, class = void>
struct deref_level {
    enum : std::size_t { value = 0 };
};

template <class T>
struct deref_level<T, decltype(void(*std::declval<T const &>()))> {
    enum : std::size_t { 
      value= deref_level<decltype(*std::declval<T const &>())>::value + 1
    };
};