C/C++ Technique[技巧]

C/C++ 技巧

我不敢正视你的眼睛,我怕我看你的每一眼都是在表白。

一、模板

1.C语言中’#’ 和 ‘##’ 的模板用法

#运算符

#运算符将一个宏的参数转换为字符串字面量。它仅允许出现在带参数的宏的替换列表中。如:

#define PRINT_INT(x) printf(#x " = %d\n", x)

x之前的#运算符通知预处理器根据PRINT_INT的参数创建一个字符串字面量。
因此,调用 “PRINT_INT(i/j);” 等同于:

printf("i/j" " = %d\n", i/j);

而在C语言中相邻的字符串字面量会被合并
因此上边的语句等价于:printf(“i/j = %d\n”, i/j);


##运算符

##运算符可以将两个记号(例如标识符)“粘”在一起,成为一个记号。(##运算符被称为“记号粘合”。)如果其中一个操作数是宏参数,“粘合”会在当形式参数被相应的实际参数替换后发生。

例如我们需要定义一个加法函数

int int_add(int a, int b)
{
    return a + b;
}

但是这种情况下,如果我们要计算float类型的数据怎么办?重新在定义一个是可以的,但是如果有更多的类型呢?难道一个个全部定义嘛,这里有更好的办法。

#define GENERIC_ADD(type) \
type type##_add(type a, type b) \
{ \
	return a + b; \
} \

现在,如果我们需要一个float类型的加法,只需要这一行代码

GENERIC_ADD(float)

预处理器会自动展开为

float float_add(flaot a, float b) 
{ 
	return a + b; 
}

2.C++ Template模板

1、类模板的格式为:
    template<class  形参名,class 形参名,…>
    class 类名{ ... };

类模板和函数模板都是以template 开始后接模板形参列表组成,模板形参不能为空,一但声明了类模板就可以用类模板的形参名声明类中的成员变量和成员函数,即可以在类中使用内置类型的地方都可以使用模板形参名来声明。比如

template<class T> class A
{
    public: 
    T a;
    T b; 
    T hy(T c, T &d);
};

当我们实例化一个类 m 时就可以这样:

A<int> m;

这样上面的类A中所有 T 的类型会被int 替代。

2、函数模板
template<typename  T> void swap(T& t1, T& t2) {
    T tmpT;
    tmpT = t1;
    t1 = t2;
    t2 = tmpT;
}

用法:

int num1 = 1, num2 = 2;
swap<int>(num1, num2);
3、模板的偏特化和全特化
/* 模板 */
template<typename T1, typename T2>
class Test
{
public:
    Test(T1 i,T2 j):a(i),b(j){cout<<"模板类"<<endl;}
private:
    T1 a;
    T2 b;
};

/* 模板全特化 */
template<>
class Test<int , char>
{
public:
    Test(int i, char j):a(i),b(j){cout<<"全特化"<<endl;}
private:
    int a;
    char b;
};

/* 模板偏特化 */
template <typename T2>
class Test<char, T2>
{
public:
    Test(char i, T2 j):a(i),b(j){cout<<"偏特化"<<endl;}
private:
    char a;
    T2 b;
};

使用:

Test<double , double> t1(0.1,0.2);  
Test<int , char> t2(1,'A');  
Test<char, bool> t3('A',true);  
//依次打印:
//类模板
//全特化
//偏特化
4、使用枚举替代 class/typename 关键字
#include <iostream>

enum type_enum{
    MYTYPE_INT = 1,
    MYTYPE_FLOAT,
    MYTYPE_STR
};

/* 与传统模板不同,这里使用的枚举替代了class/typename */
template<type_enum T>
struct T_Struct
{
    typedef void type;
};

/* 模板的全特化 */
template<> struct T_Struct<MYTYPE_INT> {typedef int type;};
template<> struct T_Struct<MYTYPE_FLOAT> {typedef float type;};
template<> struct T_Struct<MYTYPE_STR> {typedef char* type;};

int main(){
    /* 模板使用 */
    T_Struct<MYTYPE_INT>::type a = 10;
    T_Struct<MYTYPE_FLOAT>::type b = 10.99;
    T_Struct<MYTYPE_STR>::type c = "hello world\n";

    std::cout << "T_Struct<MYTYPE_INT>::type a = " << a << std::endl;
    std::cout << "T_Struct<MYTYPE_FLOAT>::type b = " << b << std::endl;
    std::cout << "T_Struct<MYTYPE_STR>::type c = " << c << std::endl;

    return 0;
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!