C++ Concepts 的两个技巧
其实是 C++ 模板的技巧,本文包含两个方面:实现模板函数的“偏特化”的效果,以及阻止字符串字面量隐式转换成 bool。
模板函数“偏特化”
模板函数是不能偏特化的,模板类偏特化的语法用到模板函数上编译器是不认识的。
但是可以用一些模板技巧来实现偏特化的效果,当然本质还是函数的重载。这里用 C++ Concepts 来实现,其实用 SFINAE 也可以。
1 | // 默认模板函数,返回类型的默认值(默认构造函数) |
字符串字面量隐式转换成bool
考虑下面代码所实现的 print
函数,它有两个重载,一个用来打印 bool 值,一个用来打印任意字符串。
下面的代码看起来没什么问题,但当 print
函数遇到字符串字面量(string literal)时,编译器会选择调用打印 bool 值的那个重载,而不是打印字符串的那个重载。
1 | void print(bool v) |
这是因为字符串字面量的本质是个数组(const char[]
),编译器首先把它退化成了指针(const char*
),然后隐式地将它转换为了 bool 值。
这个“从指针到 bool”的隐式转换通常用来判断一个指针是否等于 NULL。
1 | int* p = static_cast<int*>(malloc(sizeof(int[4]))); |
如果要阻止这种隐式转换,可以考虑的一种方案是让打印 bool 值的重载变成模板函数,然后用 C++ concepts 限制它只能接受 bool 值。
1 | template<typename T> |
其他的重载不需要修改,然后代码就可以正常工作了。
C++ Concepts 的两个技巧