C++11 - Derleme zamanında tür belirleyiciler (type traits)


#1

Basitçe derleme zamanında tür hakkında bilgi edinmemizi sağlarlar. Kullanımları oldukça basittir:


#include <iostream>
#include <memory>
#include <type_traits>

using namespace std;

class A
{
public:
    ~A(){cout << "~A()" << endl;}
     A& operator=(const A&) { return *this; }
};

int main() 
{    
    cout << boolalpha << endl;
    
    cout << is_object<int>::value << endl;
    cout << is_object<int&>::value << endl;
    cout << is_object<A>::value << endl;
    cout << is_object<A&>::value << endl;
    
    cout << "-----------------------------" << endl;
    
    struct B {};
 
    enum class C {};   
    
    cout << is_class<A>::value << endl;
    cout << is_class<B>::value << endl;
    cout << is_class<C>::value << endl;
    cout << is_class<int>::value << endl;    
    
    cout << "-----------------------------" << endl;
    
    function<void()> f = [](){cout << "is function object move assignable ?" << endl;};

    cout << is_move_assignable<B>::value << endl;
    cout << is_move_assignable<C>::value << endl;
    cout << is_move_assignable<decltype(f)>::value << endl;
    cout << is_move_assignable<A>::value << endl;
 
}

Başka bir kullanım alanları ise şablon (template) fonksiyonları için bir nevi koşul veya kısıtlama getirmek için de kullanılırlar. Temel olarak SFINAE (Substitution failure is not an error) prensibine dayanırlar. Kısacası derleyici, şablon fonksiyon overloadlarını yazarken oluşan hatayı görmezden gelir ve diğer fonksiyonları yazmaya devam eder. Tipik olarak std::enable_if ile kullanılırlar, Örneğin:

using namespace std;

class A
{   
public:
    
    friend ostream &operator<<(ostream &os, const A&) 
    {
        os << "class A" << endl; 
    }
};

template <class T>
typename enable_if<is_integral<T>::value, T>::type
println(T a)
{
    cout << "if T is a integral type: " << a << endl;
};


template <class T>
typename enable_if<is_object<T>::value, T>::type
println(T &a)
{
    cout << "if T is a object type: " << a << endl;
};

int main(int argc, char**argv) 
{
    
    A a;
    
    println(5);
    println(a);
    
    return 0;
}

Örnekte görüldüğü üzere println fonksiyonu iki farklı şekilde şablonu üretiliyor. “enable_if<is_object::value, T>::type” ifadesi ile sadece istenen türlerle o fonksiyonun çağrılmasına olanak veriyor. is_object aslında derleme zamanında gelen türün nesne mi olup olmadığını test etmemizi sağlıyor. Böylelikle kullanıma göre derleme zamanında uygun şablon fonksiyonlar yazılacak.

type traitslerin aşağıdaki linkte bir listesini bulabilirsiniz:

type traits.