C ++ Traits Classes

Reference Bowen https://blog.csdn.net/lihao21/article/details/55043881

Traits classes of action is primarily used to provide the user type information. In C ++, the traits used to always be implemented as a struct, but they are often referred to as traits classes.

In order to clearly understand the traits of principle, let's look at the key technologies used traits - template specialization and partial specialization.

Model plate specialized (Template Specialization)

The so-called specialization, that is, the generic stuff and made specific by, literally interpreted, it is some specialization is designated as an existing template parameter, so that before without any constraints template parameters, subject to certain modified, or completely specified down.

Let's look at a common definition of the next function template:

template<typename T>
struct my_is_void {
    static const bool value = false;
};

Then, for the void type, we have to following specializations:

template<>
struct my_is_void<void> {
    static const bool value = true;
};

Test code is as follows:

my_is_void<bool> t1;
cout << t1.value << endl;  // 输出0
my_is_void<void> t2;
cout << t2.value << endl;  // 输出1

When declaring my_is_void<void> t2;when using a specialized version, so the valuevalue of 1.

Specializations (Patial Spcialization)

Partial specialization is only a part but not all of the specified template parameters, or part of the argument, but not all properties . (Template function only full specialization, no partial specialization)

template<typename T>
struct my_is_pointer {
    static const bool value = false;
};

We limit the template parameter T, which requires a pointer type:

template<typename T>
struct my_is_pointer<T*> {
    static const bool value = true;
};

test:

my_is_pointer<int> p1;
cout << p1.value << endl;  // 输出 0,使用原始模板
my_is_pointer<int*> p2;
cout << p2.value << endl;  // 输出 1,使偏特化模板,因为指定了 int * 类型的参数

typename

The following statement template, class and typename What is the difference?

template<class T> class Test;
template<typename T> class Test;

The answer is no different . But in addition, C ++ is not always the class and typename regarded as equivalent. Sometimes we got to use typename.

By default, C ++ language is assumed that the name is not the type of access by the scope operator. So, if you want to use a type member of a template type parameter, you must explicitly tell the compiler that the name is a type . We accomplish this by using the keyword typename:

template<typename T>
typename T::value_type top(const T &c)
{
    if (!c.empty())
        return c.back();
    else
        return typename T::value_type();//必须加typename
}

function expects a top container type argument, it uses the specified return type typename

Test code:

vector<int> vec;
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);
cout << top<vector<int> >(vec) << endl;  // 输出3

When we wish to inform the compiler to a name indicates the type, you must use the keyword typename, but can not use the class.

Traits Classes

Having background knowledge, we officially entered the traits

We know that in the STL containers and algorithms are separate from each other independent design, through contact between the container iterators and algorithms together. Then, the algorithm is how to extract the type of container element from the iterator class is? Yes, this is the traits classes of functions we are saying.
Type referents iterator, the iterator is called the value_type . Let's implement a simple simulation of iterator traits classes.

template<class IterT>
struct my_iterator_traits {
    typedef typename IterT::value_type value_type;
};

my_iterator_traits is actually a class template, which contains a type of statement.

For my_iterator_traits, we'll declare a partial specialization version.

template<class IterT>
struct my_iterator_traits<IterT*> {
    typedef IterT value_type;
    //即如果 my_iterator_traits 的实参为指针类型时,
    //直接使用指针所指元素类型作为 value_type。
};

To test whether the type of the iterator element my_iterator_traits correct extraction, let's write the following test functions.

void fun(int a) {
    cout << "fun(int) is called" << endl;
}

void fun(double a) {
    cout << "fun(double) is called" << endl;
}

void fun(char a) {
    cout << "fun(char) is called" << endl;
}

We function overloading way to test the type of element.

Test code is as follows:

my_iterator_traits<vector<int>::iterator>::value_type a;
fun(a);  // 输出 fun(int) is called
my_iterator_traits<vector<double>::iterator>::value_type b;
fun(b);  // 输出 fun(double) is called
my_iterator_traits<char*>::value_type c;
fun(c);  // 输出 fun(char) is called

For ease of understanding, we posted here a simplified version of vector iterator declaration code:

template <class T, ...>
class vector {
public:
    class iterator {
    public:
        typedef T value_type;
        ...
    };
...
};

Let's explain the my_iterator_traits<vector<int>::iterator>::value_type a;meaning of the statement:

vector<int>::iteratorFor the vector<int>iterator, the iterator contains value_type declared by the code vector may know iterator value_type is the type int.
Then, my_iterator_traits<vector<int>::iterator>we will adopt a common version my_iterator_traits, that my_iterator_traits<vector<int>::iterator>::value_typeuse typename IterT::value_typethis type of statement is here IterT vector<int>::iterator, so the entire statement extracted type of type int.

It is a similar process for the extraction of type double vector iterator.

While my_iterator_traits<char*>::value_typeusing my_iterator_traitsPartial specializations directly return char type.

Seen in this light, by my_iterator_traits, we extract the correct iterator type referred element.

Summarize what we have designed and implemented a traits class process:

  1. We hope that a plurality of types of confirmation information can be obtained, e.g., iterator for the above, we want to achieve the type referred iterator element;
  2. Choose a name for the information, for example, above we named value_type;
  3. Provide a template and a set of specialized versions (for example, our above my_iterator_traits), the type of content that contains the relevant information we want to support.

Guess you like

Origin www.cnblogs.com/zhxmdefj/p/12530982.html