无隐式转换下的函数重载检测与条件调用问题
无隐式转换下的函数重载检测与条件调用问题
看起来你是在C++里搞函数重载的条件调用,但碰到了隐式转换相关的坑对吧?先把你的场景再理一遍:
你手上有一堆func的重载,核心就俩签名:
void func(const my_type1&); void func(const my_type2&, hash_t);
然后写了个模板函数func_imp,想用if constexpr配合has_func_with_2nd_param_v这个检测工具,根据函数是否存在来决定调用哪个func版本:
template <typename T> void func_imp(const T& t, hash_t hash){ if constexpr (has_func_with_2nd_param_v<T>){ func(t, hash); }else{ func(t); } }
但现在你碰到了隐式转换相关的问题——大概率是你的has_func_with_2nd_param_v检测逻辑没排除隐式转换,导致判断出错?比如明明不想让隐式转换触发匹配,结果检测工具误判了,或者调用时出现了歧义编译错误?
咱来解决这个问题:
核心问题:检测逻辑要排除隐式转换
默认的SFINAE检测可能会把隐式转换也算进去,比如如果T能隐式转成my_type2,那func(const my_type2&, hash_t)会被认为是对T有效的,但你要的应该是精确匹配的情况对吧?
那我们调整检测模板,确保只检测是否存在能直接接受const T&和hash_t的func重载,完全不考虑隐式转换:
#include <type_traits> // 基础模板:默认认为不存在带第二个参数的func template <typename T, typename = void> struct has_func_with_2nd_param : std::false_type {}; // 特化版本:只有当func(const T&, hash_t)能被精确调用时,返回true template <typename T> struct has_func_with_2nd_param<T, std::void_t<decltype(func(std::declval<const T&>(), std::declval<hash_t>()))>> : std::true_type {}; // 变量模板,方便直接使用 template <typename T> inline constexpr bool has_func_with_2nd_param_v = has_func_with_2nd_param<T>::value;
调整后的调用逻辑
用这个新的检测工具后,func_imp的判断就精准了:
- 如果
T是my_type2,has_func_with_2nd_param_v<T>会返回true,调用带hash_t的重载; - 如果
T是my_type1,检测返回false,调用无第二个参数的重载; - 对于其他类型,只有当存在精确匹配
func(const T&, hash_t)的重载时才会走第一个分支,完全不会因为隐式转换误判。
要是你还想进一步限制else分支只能调用my_type1的精确匹配,那可以再加个static_assert或者额外的检测,不过看你的需求,上面的调整应该已经能解决隐式转换带来的问题了。
备注:内容来源于stack exchange,提问作者Biggy Smith
相关产品推荐
相关产品推荐

