template<typename T1>class A{public: template<typename T2> A(T2 v1, T2 v2); // 泛化版本 template<typename T3, typename T4> void myft(T3 tmpt, T4 tmpt2) { std::cout << "myft 泛化版本,tmpt: " << tmpt << ",tmpt2:" << tmpt2 << std::endl; } // 偏特化版本,实际上还是之前提到的重载。 template<typename T4> void myft(int tmpt, T4 tmpt2) { std::cout << "myft(int, T4) 版本,tmpt: " << tmpt << ",tmpt2:" << tmpt2 << std::endl; } // 全特化版本 template<> voidmyft(int tmpt, float tmpt2) { std::cout << "myft<> 版本,tmpt: " << tmpt << ",tmpt2:" << tmpt2 << std::endl; }};
这段代码来自笔者学习的一本书《C++新经典:模板与泛型编程》。这本书很好,学习 template 首推。但是,书里应该还是存在一些问题。上面的 myft() 函数,全特化版本,代码完全来源于书里,在 class 内部定义,而且,书里给出运行结果。看起来非常棒,写法也很合理。但是,问题出现了。我在 ubuntu22 系统里编译这段代码,编译报错了:template.cpp:51:14: error: explicit specialization in non-namespace scope ‘class A<T1>’ 51 | template<> | ^
按理说,书的作者水平很高,不会有这样的错误,但是问题就出现了。我推测:应该是编译环境不同,书里的演示环境是 vs,我的是 g++,可能是不同编译的处理不一样。书里有不止这一处差异了。所以,再提醒一下我自己和兄弟们:要实际动手去做,再简单也要动手做,眼睛会了不代表它就一定是你想的那样。这里只列出正确写法,也是我编译通过的代码。原因,可以去问千问,这里就不贴了。顺便再提一嘴,就算是强入千问,也不能完全相信,发现前后矛盾的说法,也得多次求证。template<>template<>void A<int>::myft(int tmpt, float tmpt2){ std::cout << "myft<> 版本,tmpt: " << tmpt << ",tmpt2:" << tmpt2 << std::endl;}
把全特化的函数定义拿到 class 的外面,并且,要注意:A<int>,全特化就要连模板都一起做了。这部分我也还是存疑,以后深入学习再看看 STL 里面有没有相关例子。