欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

模板偏特化和默认模板参数的匹配顺序

程序员文章站 2022-03-09 19:53:20
...

在阅读Boost.ASIO的时候看到了下面这种写法:

template <typename CompletionToken, typename Signature = void>
class async_result
{
public:
//...
  typedef CompletionToken completion_handler_type;
  
  async_result<completion_handler_type> legacy_result_;
};

template <typename Handler>
class async_result<Handler>
{
//...
};

先开始没注意到下面这个偏特化版本,导致我始终不明白上面legacy_result_的成员声明那种写法,这看起来不是死循环了吗。但注意到偏特化模板类后又注意到一个问题,对于这种默认模板参数与偏特化都能匹配的时候,是实例化那种版本的模板类。(虽然从上面的写法中已经可以推理出答案了。。)

还是动手测试下:
先是在一个头文件中定义了2个模板类,模仿上面的情况。

template <class T, typename U = void>
class test {
	public:
		test() {
			std::cout << "默认模板参数版本" << std::endl;
		}
};

template <class T>
class test<T> {
public:
	test() {
		std::cout << "偏特化版本" << std::endl;
	}
};

然后在main函数中创建一个test类型的局部变量:

int main() {
	test<int> t;
}

输出

偏特化版本

看得出来优先匹配偏特化的版本。

接下来再做另一个测试,这次改为传入2个模板参数,不过2个模板类的定义也要稍微改下:

template <class T, typename U = void>
class test {
	public:
		test() {
			std::cout << "默认模板参数版本" << std::endl;
		}
};

template <class T>
class test<T, int> {   // 注意这里多了一个模板参数
public:
	test() {
		std::cout << "偏特化版本" << std::endl;
	}
};

这里只改了偏特化版本,使其具有2个模板参数。
此时main函数中再创建一个test变量:

int main() {
	test<int, int> t;
	test<int> t2;
}

输出

偏特化版本
默认模板参数版本

总结

在偏特化版本和模板参数版本都能匹配的情况下,优先匹配偏特化版本。

相关标签: 模板