C++ traits

【本文链接】

http://www.cnblogs.com/hellogiser/p/cplusplus-traits.html

【分析】

什么是traits?其实它并不是一个新的概念,上个世纪90年代中期就已经被提出,只是到了这个世纪才在各个C++库中被广泛使用,而我也是在这个概念诞生十多年后才接触到它。C++之父Bjarne Stroustrup对traits有如下的描述:

Think of a trait as a small object whose main purpose is to carry information used by another object or algorithm to determine "policy" or "implementation details".

我不知道官方或一些书上是如何去解释traits的,我的理解是:
当函数,类或者一些封装的通用算法中的某些部分会因为数据类型不同而导致处理或逻辑不同(而我们又不希望因为数据类型的差异而修改算法本身的封装时),traits会是一种很好的解决方案。

【is_void is_pointer代码】

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
 
/*
    version: 1.0
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/9/22
*/


#include "stdafx.h"
#include "iostream"
using namespace std;

// generic template
template<typename T>
struct is_void_x
{
    
// enum {value = false} ;
    static const bool value = false;
};

//specialization for void
template<>
struct is_void_x<void>
{
    
static const bool value = true;
};

void test_is_void()
{
    cout << 
"is void...\n";
    cout << is_void_x<
int>::value << endl;
    cout << is_void_x<
void>::value << endl;
}

// generic template
template<typename T>
struct is_pointer_x
{
    
static const bool value = false;
};

// partial specialization for pointer
template<typename T>
struct is_pointer_x<T *>
{
    
static const bool value = true;
};

void test_is_pointer()
{
    cout << 
"is pointer...\n";
    cout << is_pointer_x<
int>::value << endl;
    cout << is_pointer_x<
int *>::value << endl;
}

int main()
{
    test_is_void();
    test_is_pointer();
}

再看一个例子。

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
 
/*
    version: 1.0
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/9/22
*/


#include "stdafx.h"
#include "iostream"
using namespace std;

template<typename T>
class TypeTraits
{
public:
    
typedef double ReturnType;
};

template<>
class TypeTraits<char>
{
public:
    
typedef int ReturnType;
};

template<>
class TypeTraits<short>
{
public:
    
typedef int ReturnType;
};

template<>
class TypeTraits<int>
{
public:
    
typedef int ReturnType;
};

template<>
class TypeTraits<float>
{
public:
    
typedef double ReturnType;
};

template<>
class TypeTraits<double>
{
public:
    
typedef double ReturnType;
};

template <typename T, typename TypeTraits>
typename TypeTraits::ReturnType average_x(const T const *begin, const T const *end)
{
    TypeTraits::ReturnType total = TypeTraits::ReturnType();
    
//T total = T();
    int count = 0;
    
while (begin != end)
    {
        total += * begin;
        ++begin;
        ++count;
    }
    
return total / count;
}

void test_average()
{
    
int a[] = {12345};
    cout << average_x<
int, TypeTraits<int> >(a, a + 5) << endl; // 3

    
char str[] = "traits";
    cout << average_x<
char, TypeTraits<char>>(str, str + 6) << endl; // -17 ????  ===>110
}

int main()
{
    test_average();
}

【参考】

http://accu.org/index.php/journals/442

http://blog.csdn.net/my_business/article/details/7891687

http://www.cppblog.com/youxia/archive/2008/08/30/60443.html

http://stackoverflow.com/questions/3979766/how-do-traits-classes-work

http://en.cppreference.com/w/cpp/language/partial_specialization