C++如何从模板类的特化构造函数中调用通用模板构造函数?
你之前的写法出现死循环的根本原因是:你已经完全特化了Test<Foo>的Test(Foo*)构造函数,当你在特化构造的初始化列表中写Test(x)时,重载决议会优先匹配你已经特化的这个同签名构造函数,最终形成自调用的递归死循环。
下面是两种可行的解决方法:
方案1:抽离通用逻辑到独立初始化函数(兼容性最好)
把通用构造中除了t初始化之外的所有公共逻辑抽成私有成员函数,通用构造和特化构造都调用该函数即可,对C++标准版本没有要求,逻辑简单直观:
template <class T> class Test { public: Test(T* x); private: const T* const t; int i{0}; // 新增私有初始化函数,存放所有通用逻辑 void init() { // 通用初始化逻辑写在这里 } }; // 通用构造实现 template <class T> Test<T>::Test(T* x) : t{x} { init(); } // 特化构造实现 template <> Test<Foo>::Test(Foo* x) : t{x} { init(); i = 1; } template <> Test<Bar>::Test(Bar* x) : t{x} { init(); i = 2; }
方案2:标签分发实现构造委托(适配成员初始化场景)
如果你的通用逻辑需要在成员初始化列表阶段执行(比如要初始化其他const成员、非默认构造的成员),可以加一个无意义的标签参数区分通用构造和特化构造,避免重载决议匹配到特化版本:
template <class T> class Test { public: Test(T* x); private: const T* const t; int i{0}; // 新增私有标签类型和构造重载 struct general_constructor_tag {}; Test(T* x, general_constructor_tag); }; // 带标签的通用构造实现所有公共逻辑 template <class T> Test<T>::Test(T* x, general_constructor_tag) : t{x} { // 所有通用初始化逻辑写在这里 } // 原有通用构造委托带标签的版本 template <class T> Test<T>::Test(T* x) : Test(x, general_constructor_tag{}) {} // 特化构造直接委托带标签的通用构造,不会触发死循环 template <> Test<Foo>::Test(Foo* x) : Test(x, general_constructor_tag{}) { i = 1; } template <> Test<Bar>::Test(Bar* x) : Test(x, general_constructor_tag{}) { i = 2; }
内容的提问来源于stack exchange,提问作者T. J. Evers
相关产品推荐
相关产品推荐

