C++如何基于构造函数类型实现方法调用的编译期静态断言校验
C++ 编译期校验不同构造函数实例的方法调用权限
方案1:拆分类层级 + 工厂函数(兼容C++11及以上版本)
核心思路是将公共方法foo放在基类,仅允许带参构造实例调用的bar方法放在派生类,通过静态工厂方法返回对应类型的实例,从类型层面直接禁止默认构造实例调用bar:
#include <iostream> // 基类:仅包含所有实例都可调用的公共方法 class FooBase { public: void foo() { std::cout << "call foo" << std::endl; } protected: // 构造函数保护,禁止外部直接构造基类 FooBase() = default; }; // 派生类:仅带参构造的实例会返回该类型,包含bar方法 class Foo : public FooBase { public: void bar() { std::cout << "call bar" << std::endl; } private: // 构造函数私有,仅允许工厂方法构造 Foo(int a) : FooBase() {} friend Foo create_foo_with_param(int a); friend FooBase create_default_foo(); }; // 静态工厂方法:默认构造返回基类类型 FooBase create_default_foo() { return FooBase(); } // 静态工厂方法:带参构造返回派生类类型 Foo create_foo_with_param(int a) { return Foo(a); }
使用示例:
int main() { auto foo1 = create_default_foo(); foo1.foo(); // 编译通过 // foo1.bar(); // 编译错误:FooBase没有bar方法 auto foo2 = create_foo_with_param(10); foo2.foo(); // 编译通过 foo2.bar(); // 编译通过 return 0; }
方案2:模板类 + C++20 约束(语法更简洁)
如果可以使用C++20及以上标准,可以直接用模板非类型参数标记实例的构造类型,通过requires约束限制bar方法的调用权限:
#include <iostream> template<bool HasBar = false> class Foo { public: // 默认构造:对应HasBar为false Foo() = default; // 带参构造:对应HasBar为true Foo(int a) requires (!HasBar) : Foo<true>() {} void foo() { std::cout << "call foo" << std::endl; } void bar() requires (HasBar) { std::cout << "call bar" << std::endl; } }; // 推导指引,确保带参构造自动生成Foo<true>类型 Foo(int) -> Foo<true>;
使用示例:
int main() { Foo foo1; // 自动推导为Foo<false> foo1.foo(); // 编译通过 // foo1.bar(); // 编译错误:不满足requires约束 Foo foo2(10); // 自动推导为Foo<true> foo2.foo(); // 编译通过 foo2.bar(); // 编译通过 return 0; }
两种方案都完全在编译期完成校验,只要调用不符合规则就会直接触发编译错误,不需要运行时的状态判断和异常抛出。
内容的提问来源于stack exchange,提问作者elo
相关产品推荐
相关产品推荐

