19 Şubat 2018 Pazartesi

type_traits

Giriş
C++11 ile gelen type_traits metodları meta programming için kullanılıyor. is_xxx() ve has_xxx() ile başlayan bir sürü metod var.

Nasıl Yazılır
is_container isimli kendi metodumuzu yazmak isteyelim. Eğer parametrenin iterator inner sınıfı varsa true dönsün isteyelim. Şöyle yaparız.
#include <vector>
#include <string>
#include <iostream>
#include <type_traits>

template<typename ...>
using void_t=void;

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

template<typename T>
struct is_container<T, void_t<typename T::iterator>> : std::true_type {};

int main()
{
    std::cout << is_container<int>::value << std::endl;

    std::cout << is_container<std::vector<int>>::value << std::endl;
    return 0;
}

is_abstract metodu
Örnek ver

is_arithmetic metodu
is_arithmetic yazısına taşıdım

is_assignable metodu
Sağdaki parametrenin, soldakine atanıp atanamayacağını döner. Elimizde şöyle bir kalıtım olsun
class X
{
};

class Y : public X
{
};
Y'ye point eden bir nesnenin X'e point eden bir değişkene atanabileceğini şöyle kontrol ederiz.
std::is_assignable<X*&, Y*>::value
is_base_of metodu
Verilen container sınıfının iteratorünün bidirectional olup olmadığını şöyle kontrol ederiz.
static_assert(std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename C1::iterator>::iterator_category>::value, "");

is_const metodu
is_const yazısına taşıdım.

is_enum metodu
is_enum yazısına taşıdım.

is_function metodu 
is_function yazısına taşıdım.

is_lvalue_reference metodu
Parametrenin l-value ya da r-value olduğunu belirtir. Şöyle bir kullanırız.
template <typename T>
constexpr bool is_lvalue(T&&) {
  return std::is_lvalue_reference<T>{};
}
Şöyle çağırırız.
std::string a("Hello");
is_lvalue(std::string()); // false
is_lvalue(a); // true  
is_integral metodu
Açıklaması şöyle. Parametrenin bool, char, veya char tipin, short, int tipi gibi bir şey olup olmadığını döner. is_arithmetic'teki gibi float bu gruba dahil değildir.
Checks whether T is an integral type. Provides the member constant value which is equal to true, if T is the type boolcharchar16_tchar32_twchar_tshortintlonglong long, or any implementation-defined extended integer types, including any signed, unsigned, and cv-qualified variants. Otherwise, value is equal to false.
std::true_type veya std::false_type olarak dispatch edilir.
class OraclePreparedStatement
{
public:
    template<typename T>
    void bind_param(uint32_t col_index, T&& param)
    {
        bind_param_impl(col_index, std::forward<T>(param), 
                        std::is_integral<std::remove_reference_t<T>>());
    }

private:
    template<typename T>
    void bind_param_impl(uint32_t col_index, T&& param, std::true_type)
    {
        statement->setNumber(col_index, oracle::occi::Number(param));
    }

    template<typename T>
    void bind_param_impl(uint32_t col_index, T&& param, std::false_type)
    {
        statement->setString(col_index, std::forward<T>(param));
    }

    OracleConnection::StatementWrapper statement;
};
is_move_constructible metodu
constructible traits yazısına taşıdım.

is_nothrow_constructible metodu
constructible traits yazısına taşıdım.

is_pod metodu
Bu metod C++20 ile deprecate ediliyor. Açıklaması şöyle.
Deprecating the notion of “plain old data” (POD). It has been replaced with two more nuanced categories of types, “trivial” and “standard-layout”. “POD” is equivalent to “trivial and standard layout”, but for many code patterns, a narrower restriction to just “trivial” or just “standard layout” is appropriate; to encourage such precision, the notion of “POD” was therefore deprecated. The library trait is_pod has also been deprecated correspondingly.
Bu metod yerine is_trivial() veya is_standard_layout() metodlarını kullanmak gerek.

is_polymorphic metodu
Örnek ver

is_pointer metodu
Örnek
Sadece pointer tipleri kabul eden bir kod için şöyle yaparız.
template <typename T> struct MyTemplate
{
    static_assert(std::is_pointer<T>::value, "Expected a pointer");

    // T = value_type*
    using value_type = std::remove_pointer_t<T>;
};
Örnek
Pointer olan ve olmayan parametreleri ayırmak için şöyle yaparız.
template <class T> 
void Foo(const T* x) {
  std::cout << "I am the pointer overload" << std::endl;
}

template <class T> 
typename std::enable_if<!std::is_pointer<T>::value>::type 
Foo(const T& x) {
  std::cout << "I am the reference overload" << std::endl;
}
is_trivial metodu
Constructor veya Copy Constructor yoksa true döner. Şöyle yaparız.
std::is_trivial<std::atomic<int>>::value, "std::atomic<int> not trivial");

is_trivially_copyable metodu
std::is_trivially_copyable yazısına taşıdım.

is_trivially_destructible metodu
Destructor yoksa true döner. Elimizde şöyle bir struct olsun.
struct A {
public:
    A(int a, int c): a_(a+c), c_(a-c) { }
    A(const A& arg): a_(arg.a_), c_(arg.c_) { }
    int a_;
    char c_;
};
Şöyle yaparız.
std::is_trivially_destructible<A>::value
is_signed metodu
Örnek ver.

is_standard_layout metodu
Açıklaması şöyle.
This is for backward compatibility with C.
Şöyle yaparız.
#include <iostream>
#include <type_traits>

struct s_ref {
    int &foo;
};

struct s_ptr {
    int *foo;
};

int main(int argc, char *argv[])
{
  std::is_standard_layout<struct s_ref>::value << std::endl; //false
  std::is_standard_layout<struct s_ptr>::value << std::endl; //true
  return 0;
}
is_trivially_constructable metodu
constructible traits yazısına taşıdım.

is_unsigned metodu
bool için bile çalışır ve true döner.
std::is_unsigned<bool>::value
is_void metodu
Açıklaması şöyle.
Provides the member constant value that is equal to true, if T is the type void, const void, volatile void, or const volatile void.
has_virtual_destructor metodu
Örnek yaz

remove_reference metodu
Açıklaması şöyle
If the type T is a reference type, provides the member typedef type which is the type referred to by T. Otherwise type is T.
İmzası ve gerçekleştirimi şöyle olabilir.
template< class T > struct remove_reference      {typedef T type;};
template< class T > struct remove_reference<T&>  {typedef T type;};
template< class T > struct remove_reference<T&&> {typedef T type;};

Elimizde şöyle bir kod olsun
template <typename T> 
typename remove_reference<T>::type Magic(T t) { 
    return t; 
}
Bu kodu şöyle çağırırsak şu sonuçları alırız.
Magic(int i) -> int i
Magic(int& i) -> int i
Magic(int&& i) -> int i 




Hiç yorum yok:

Yorum Gönder