如何重载cb函数模板解决C2535成员函数重复定义编译错误
问题原因
C++标准中,函数模板的默认模板参数不参与函数签名的计算,你原本的两个单参数cb模板的签名是完全等价的:两者的模板参数列表均为<typename F, typename>,函数形参列表均为(const F&),所以编译器会判定为重复定义,抛出C2535错误。
修复方案
把std::enable_if_t从默认类型模板参数的位置,移动到非类型模板参数的默认值位置,这样两个模板的签名就能被正确区分,不会被判定为重复定义,修改后完整代码如下:
template <typename T> class notify_property { public: virtual ~notify_property() {} //1 无参数回调版本 template <typename F, std::enable_if_t<std::is_void_v<std::invoke_result_t<std::decay_t<F>>>>* = nullptr> void cb(const F& task) { set_cb([task] { try { task(); } catch (...) {} }); } //2 接受T类型参数的回调版本 template <typename F, std::enable_if_t<std::is_void_v<std::invoke_result_t<std::decay_t<F>, std::decay_t<T>>>>* = nullptr> void cb(const F& task) { set_cb([this, task] { try { task(_value); } catch (...) {} }); } //3 接受T+额外参数的回调版本(同步改写避免潜在冲突) template <typename F, typename... A, std::enable_if_t<std::is_void_v<std::invoke_result_t<std::decay_t<F>, std::decay_t<T>, std::decay_t<A>...>>>* = nullptr> void cb(const F& task, const A &...args) { set_cb([this, task, args...] { try { task(_value, args...); } catch (...) {} }); } virtual T& operator= (const T& f) { if (f != _value) { _value = f; if (_cb != nullptr) _cb(); } return _value; } virtual const T& operator() () const { return _value; } virtual explicit operator const T& () const { return _value; } virtual T* operator->() { return &_value; } protected: template <typename F> void set_cb(const F& cb) { _cb = std::function<void()>(cb); } std::function<void()> _cb = nullptr; T _value; };
内容的提问来源于stack exchange,提问作者Андрей Петрашевич
相关产品推荐
相关产品推荐

