static_cast与模板转换函数问题:仅Dim=0时允许Unit类转换到底层类型
问题原因
核心原因是你将enable_if作为类型模板参数的默认值使用时,转换运算符作为模板函数,在隐式转换场景下没有可以推导该类型模板参数的上下文,编译器不会主动使用模板参数的默认值完成实例化,导致该转换函数直接被排除在候选集之外,static_cast找不到可用的转换路径因此报错。
解决方案
方案1:C++20及以上版本(最简洁)
使用requires约束转换函数,不需要把转换函数声明为模板,自然没有模板参数推导的问题:
#include <type_traits> template<class T, int Dim> class Unit { public: explicit Unit(T const& value): _value(value) {} // 仅当Dim==0时该转换函数可用 operator T() const requires (Dim == 0) { return _value; } private: T _value; }; auto main() -> int { auto a = double{0}; auto u = Unit<double, 0>{a}; auto i = static_cast<int>(u); // 以下代码会编译失败,符合预期 // auto u2 = Unit<double, 1>{a}; // auto d = static_cast<double>(u2); return i; }
方案2:兼容C++11及以上版本
调整SFINAE的写法,把enable_if放到非类型模板参数的默认值位置,此时编译器会主动使用非类型模板参数的默认值完成实例化,转换函数可以正常进入候选集:
#include <type_traits> template<class T, int Dim> class Unit { public: explicit Unit(T const& value): _value(value) {} template<int D = Dim, typename std::enable_if<D == 0, int>::type = 0> operator T() const { return _value; } private: T _value; }; auto main() -> int { auto a = double{0}; auto u = Unit<double, 0>{a}; auto i = static_cast<int>(u); return i; }
两种方案都满足要求:仅当Dim=0时可转换到底层类型,其余场景下转换运算符不可调用,同时支持static_cast的转换需求。
内容的提问来源于stack exchange,提问作者Henk
相关产品推荐
相关产品推荐

