基于Concepts的模板派生类虚函数选择性实现问题求助
问题解决:基于Concept的虚函数条件实现
问题背景
我有一个抽象基类base和模板派生类derived,需求如下:
- 当模板类型满足
can_meowconcept时,在derived中实现基类的纯虚方法foo_base - 当类型不满足该concept时,让
foo_base留待上层派生类(如derived2)实现
当前代码中,derived<cat>可正常实例化,但实例化derived2<int>时会报错,错误信息:
<source>:28:6: error: use of function 'void wrapper<T>::foo_base() requires can_meow<T> [with T = int]' with unsatisfied constraints
错误原因
问题出在derived<T>中带约束的foo_base实现上:当T不满足can_meow时,该函数的约束不成立,编译器会判定derived<T>未实现基类的纯虚函数。但derived<T>本身并未被声明为抽象类,因此实例化derived<int>(通过derived2<int>)时,编译器找不到有效实现,直接报错。
解决方案
方案1:模板特化(推荐)
将derived<T>拆分为主模板和满足concept的特化版本,分别处理两种场景:
#include <iostream> struct cat { void meow() { std::cout << "Meow!\n"; } }; struct base { virtual void foo_base() = 0; }; template<typename T> concept can_meow = requires(T t){t.meow();}; // 主模板:不满足can_meow时,保持抽象,留待派生类实现foo_base template<class T> struct derived: public base { derived() { std::cout << "Wrapper constructor w/o meow!\n"; } void foo_base() override = 0; }; // 特化版本:满足can_meow时,直接实现foo_base template<can_meow T> struct derived<T>: public base { derived() { std::cout << "Wrapper constructor with meow!\n"; } void foo_base() final override {}; }; template<class T> struct derived2: public derived<T> { void foo_base() final override {}; }; int main() { derived<cat> c; // 正常运行 derived2<int> i; // 现在可正常实例化 return 0; }
方案2:带约束的双版本函数声明
在主模板中通过requires约束,为foo_base提供两个互斥的声明:满足concept时提供实现,否则保留纯虚:
#include <iostream> struct cat { void meow() { std::cout << "Meow!\n"; } }; struct base { virtual void foo_base() = 0; }; template<typename T> concept can_meow = requires(T t){t.meow();}; template<class T> struct derived: public base { derived() requires can_meow<T> { std::cout << "Wrapper constructor with meow!\n"; } derived() requires (!can_meow<T>) { std::cout << "Wrapper constructor w/o meow!\n"; } // 满足can_meow时提供实现 void foo_base() requires can_meow<T> final override {}; // 不满足时保留纯虚,允许派生类实现 void foo_base() requires (!can_meow<T>) override = 0; }; template<class T> struct derived2: public derived<T> { void foo_base() final override {}; }; int main() { derived<cat> c; // 正常运行 derived2<int> i; // 现在可正常实例化 return 0; }
内容的提问来源于stack exchange,提问作者user3895986
相关产品推荐
相关产品推荐

