C++带指定类型的非类型模板模板的正确语法与参数简化
简化std::optional成员指针模板参数的可行方案
这种简化是可行的,在C++17及以上标准中,利用自动推导的非类型模板参数即可实现仅传递成员指针、让编译器自动推导所属类C和optional内部类型T的效果。
正确实现代码
#include <optional> #include <type_traits> class A { public: std::optional<int> i; }; // 核心:用auto作为非类型模板参数,自动推导成员指针的类型 template <auto OptionalMemberPtr> class OptionalHolder { // 从成员指针推导所属类C using ContainingClass = std::remove_pointer_t<std::decay_t<decltype(OptionalMemberPtr)>>; // 推导optional的具体类型 using OptionalType = std::remove_reference_t<decltype(*OptionalMemberPtr)>; // 推导optional内部的T类型 using ValueType = typename OptionalType::value_type; public: void doStuff(ContainingClass& c) { // 示例操作:访问成员并判断是否有值 if (c.*OptionalMemberPtr) { // 可直接操作*c.*OptionalMemberPtr,如输出值 // std::cout << *c.*OptionalMemberPtr << std::endl; } } }; // 简化使用:仅需传递成员指针,无需显式指定C和T using OH = OptionalHolder<&A::i>;
为什么你之前的写法无法编译
你尝试的template<class T> std::optional<T> C::*这类写法属于误用模板模板参数:模板模板参数是用来匹配模板本身(比如template<typename> class Opt),而std::optional<T> C::*是一个具体的成员指针类型,并非模板,因此编译器无法识别这种语法。
兼容性说明
如果需要兼容C17之前的标准,可以通过decltype结合辅助模板实现推导,但代码会更繁琐。C17的auto非类型模板参数是最简洁的解决方案。
内容的提问来源于stack exchange,提问作者Hugal31
相关产品推荐
相关产品推荐

