#include<iostream>
#include<type_traits>
using namespace std;
void print(){}
template<typename T, typename... Types>
void print(T firstArg, Types... args)
{
std::cout << firstArg << endl; //print first argument
print(args...); // call print() for remaining arguments
}
/*
printtest 这一方式是错误的, 因为通常函数模板中 if 语句的两个分支都会被实例化。
是否使用被实例化出来的代码是在运行期间( run - time) 决定的;
而是否实例化代码是在编译期间(compile - time) 决定的。
因此如果在只有一个参数的时候调用 print()函数模板, 虽然 args...为空, if 语句中的 print(args...)也依然会被实例化, 但此时没有定义不接受参数的 print()函数,因此会报错。
*/
template<typename T, typename... Types>
void printtest(T const& firstArg, Types const& ... args)
{
cout << firstArg << endl;
if(sizeof...(args) > 0) {
printtest(args...);//即便if运行期不满足条件进入此处,依然需要实例化次处代码
}
}
/*
这里如果只给 print()传递一个参数, 那么 args...就是一个空的参数包, 此时 sizeof...(args)等于
0。 这样 if 语句里面的语句就会被丢弃掉, 也就是说这部分代码不会被实例化。 因此也就不再需要一个单独的函数来终结递归。
事实上上面所说的不会被实例化, 意思是对这部分代码只会进行第一阶段编译, 此时只会做语法检查以及和模板参数无关的名称检查(参见 1.1.3 节) 。
*/
template<typename T, typename... Types>
void print17(T const& firstArg, Types const& ... args)
{
cout << firstArg << endl;
if constexpr (sizeof...(args) > 0) {//code only available if sizeof…(args)>0 (sinceC++17)
print17(args...); //若编译期if成功则进行二阶段编译检查即进入实例化阶段,否则此处代码只进行第一阶段编译检查,即不进行实例化阶段
}
}
int main()
{
print("hello", 45, 3.14, 'c', string("world"));
//! printtest("hello", 45, 3.14, 'c', string("world"));
print17("hello", 45, 3.14, 'c', string("world"));
return 0;
}
if constexpr与二阶段编译检查分析
最新推荐文章于 2024-08-30 16:00:44 发布