如何在C++函数重载中阻止std::function向bool的隐式转换?
问题原因
函数指针可以隐式转换为bool(非空指针会被转为true),而转换为std::function属于用户定义转换。在C++重载解析规则中,标准转换序列的优先级高于用户定义转换序列,因此Object(Println)会优先匹配接受bool的构造函数#1。
解决方案
方法1:添加函数指针类型的精确重载构造函数
直接为int(*)(int*, int)类型提供精确匹配的构造函数,委托给原有的std::function构造函数。精确匹配的优先级高于任何隐式转换,因此会被优先选中:
#include <functional> #include <iostream> #include <cstdio> class Object final { public: Object(bool boolean) : type_(22) {} //#1 Object(const std::function<int(int*, int)> value) : type_(11) {} //#2 // 新增:匹配目标函数指针的精确重载 Object(int (*func)(int*, int)) : Object(std::function<int(int*, int)>(func)) {} int rettype() { return type_; }; private: int type_; }; int Println(int *args, int nargs) { printf("Println\n"); return 0; } int main() { std::cout << Object(Println).rettype() << std::endl; // 输出11 std::cout << Object(std::function<int(int*, int)>(Println)).rettype() << std::endl; // 11 std::cout << Object(true).rettype() << std::endl; // 依然输出22 }
方法2:限制bool构造函数仅接受bool类型
通过SFINAE技术,让bool构造函数只对真正的bool类型生效,排除掉可隐式转换为bool的类型(如函数指针):
#include <functional> #include <iostream> #include <cstdio> #include <type_traits> class Object final { public: // 仅当T是bool类型时,此构造函数才可用 template <typename T, typename = std::enable_if_t<std::is_same_v<std::decay_t<T>, bool>>> Object(T boolean) : type_(22) {} //#1 Object(const std::function<int(int*, int)> value) : type_(11) {} //#2 int rettype() { return type_; }; private: int type_; }; int Println(int *args, int nargs) { printf("Println\n"); return 0; } int main() { std::cout << Object(Println).rettype() << std::endl; // 输出11 std::cout << Object(std::function<int(int*, int)>(Println)).rettype() << std::endl; // 11 std::cout << Object(true).rettype() << std::endl; // 输出22 }
方法3:将bool构造函数声明为explicit
explicit关键字会禁止隐式转换调用该构造函数,函数指针无法隐式转为bool匹配#1,此时重载解析会选择需要用户定义转换的#2:
#include <functional> #include <iostream> #include <cstdio> class Object final { public: explicit Object(bool boolean) : type_(22) {} //#1 改为explicit Object(const std::function<int(int*, int)> value) : type_(11) {} //#2 int rettype() { return type_; }; private: int type_; }; int Println(int *args, int nargs) { printf("Println\n"); return 0; } int main() { std::cout << Object(Println).rettype() << std::endl; // 输出11 std::cout << Object(std::function<int(int*, int)>(Println)).rettype() << std::endl; // 11 std::cout << Object(true).rettype() << std::endl; // 正常输出22,必须显式传入bool // 注意:此时 Object(1) 这类隐式转bool的调用会编译失败,符合explicit的设计意图 }
内容的提问来源于stack exchange,提问作者FLAG
相关产品推荐
相关产品推荐

