09 函数模板⚓︎
约 609 个字 52 行代码 预计阅读时间 4 分钟
函数模板⚓︎
无论是前面讲到的类模板,还是接下来要讲的函数模板(template function
虽然我们前面提到的函数重载(function overloading)也能实现一个函数的多种版本,但是编写起来有些麻烦(复制粘贴 + 修改类型 + 有时还得稍微转化一下
其中第一行可以设置默认参数类型:
调用模板函数时,我们既可以显式指出需要传递的参数类型,比如:
也可以隐式调用,让编译器自行推断,比如:
template <typename T, typename U>
auto smarterMyMin(T a, U b)
{
return a < b ? a : b;
}
// in the main() function
cout << smarterMyMin<int>(3.2, 4) << endl;
和类模板相似,直到被使用前,函数模板不会被编译,编译器会根据实例化后(调用时)的参数类型来决定生成什么样的函数模板的具体版本,编译后生成的代码就像我们平时写的一般函数。这样代码的运行效率会有所提高。
约束和概念⚓︎
在 C++ 20 及以上的版本中,我们可以限制类模板、函数模板,以及类模板的非模板成员函数的可接受的类型,这样的限制被称为约束(constraints
// Concept
template<typename T>
concept Addable = requires (T a, T b)
{
a + b;
};
// Constainted template function
// template<typename T> requires Addable<T>
// T add(T a, T b) { return a + b; }
// A shorthand
template <Addable T> T add(T a, T b){ return a + b; }
还没完全理解,待补充
模板元编程⚓︎
通常,代码在运行期间(runtime)内运行;而在模板元编程中,代码能够在编译期间(compile time)运行一次,这样能够提升代码运行的性能和效率。下面是模板元编程的一个:
template<unsigned n>
struct Factorial
{
enum { value = n * Factorial<n - 1>::value };
};
template<>
struct Factorial<0>
{
enum { value = 1 };
};
std::cout << Factorial<10>::value << endl;
constexpr⚓︎
另外一种能让 C++ 在编译期间运行代码的方法是使用关键词 constexpr
来指明一个常量表达式。
- 常量表达式必须立即进行初始化,且在编译期间运行
- 传入常量表达式内的蚕食也应该是常量或者常量表达式
- 变量可悲声明为
constexpr
相比第一种方法,constexpr
的模板元编程更加可读,还是接着之前的例子进行修改:
constexpr double fib(int n)
{
if (n == 1) return 1;
return fib(n - 1) * n;
}
int main()
{
const long long bigval = fib(20);
std::cout << bigval << std::endl;
}
评论区