如何使用decltype或declval检测特定重载成员函数是否存在?
问题解决:检测含重载成员函数的类特性
原代码的核心问题是:当类存在重载的msg_hdr()成员函数时,decltype(St::msg_hdr)无法确定具体指向哪个重载版本,导致SFINAE条件失效。需要调整检测逻辑,通过尝试调用成员函数并验证返回值类型来实现特性检测。
修改后的完整代码
#include <iostream> #include <type_traits> struct Header { int i; int j; }; struct Data { Header& msg_hdr() { return this->_msg_hdr; } const Header& msg_hdr() const { return this->_msg_hdr; } private: Header _msg_hdr; int k; }; // 基础模板:默认判定为不存在目标成员函数 template<typename, typename = void> constexpr bool has_msg_hdr = false; // SFINAE检测分支:验证是否能调用msg_hdr()且返回值可转换为const Header& template<typename St> constexpr bool has_msg_hdr<St, std::enable_if_t< std::is_convertible_v<decltype(std::declval<St>().msg_hdr()), const Header&> >> = true; template<typename St> constexpr void check(St&& s) { if constexpr(has_msg_hdr<std::decay_t<St>>) { std::cout << "has msg_header \n"; } else { std::cout << "no msg_header \n"; } } int main(int argc, char** argv) { Data d; check(d); const Data cd; check(cd); // 测试无msg_hdr的类型 int x; check(x); return 0; }
关键修改说明
- 调用式检测:用
std::declval<St>().msg_hdr()尝试调用成员函数,SFINAE会自动匹配对应重载版本(非const对象匹配非const成员函数,const对象匹配const成员函数) - 返回值验证:通过
std::is_convertible_v确保返回值可转换为const Header&,同时覆盖非const和const版本的返回值类型 - 类型简化:用
std::decay_t替代remove_const_t + remove_reference_t,更简洁地处理参数的类型衰减
修改后,无论传递非const还是const的Data对象,都能正确检测到msg_hdr()的存在;同时对无该成员函数的类型也能正确判定。
内容的提问来源于stack exchange,提问作者virus00x
相关产品推荐
相关产品推荐

