当前std::function
不消除重载函数的歧义(参见最后的示例)。因此,当从重载函数构造或分配时,用户必须手动消除歧义(例如,使用显式强制转换),这很烦人。由于std::function
具有函数签名信息,因此它实际上可以自动消除歧义。所以,我尝试从function
中创建一个新的std::function
,最后得到以下代码。扩展标准库可能非常棘手且容易出错。所以,我想知道我是否遗漏了某些东西,或者存在更好的解决方案。具体来说,我可以为我的新std::uses_allocator
部分专门化function
吗? (可以找到代码的原始版本here)
template <typename R, typename... Args>
class function<R(Args...)> : public std::function<R(Args...)> {
private:
template <typename F_, typename F = std::decay_t<F_>>
using enable_if_fn_t = std::enable_if_t<
std::is_same<R, std::result_of_t<F(Args...)>>
::value>;
public:
using base = std::function<R(Args...)>;
function(R(*ptr)(Args...)) : base{ptr} {}
function() = default;
function(std::nullptr_t) : base{nullptr} {}
template <typename F, typename = enable_if_fn_t<F>>
function(F f) : base{std::move(f)} {}
template <typename Alloc>
function(std::allocator_arg_t tag, const Alloc& alloc)
: base{tag, alloc} {}
template <typename Alloc>
function(std::allocator_arg_t tag, const Alloc& alloc, std::nullptr_t)
: base{tag, alloc, nullptr} {}
template <typename F, typename Alloc, typename = enable_if_fn_t<F>>
function(std::allocator_arg_t tag, const Alloc& alloc, F f)
: base{tag, alloc, std::move(f)} {}
template <typename Alloc>
function(std::allocator_arg_t tag, const Alloc& alloc, const function& other)
: base{tag, alloc, static_cast<const base&>(other)} {}
template <typename Alloc>
function(std::allocator_arg_t tag, const Alloc& alloc, function&& other)
: base{tag, alloc, std::move(static_cast<base&>(other))} {}
function& operator =(R(*ptr)(Args...)) {
base::operator =(ptr);
return *this;
}
function& operator =(std::nullptr_t) {
base::operator =(nullptr);
return *this;
}
template <typename F, typename = enable_if_fn_t<F>>
function& operator =(F&& f) {
base::operator =(std::forward<F>(f));
return *this;
}
template <typename F, typename = enable_if_fn_t<F>>
function& operator =(std::reference_wrapper<F> f) {
base::operator =(f);
return *this;
}
};
namespace std {
template <typename R, typename... Args, typename Alloc>
struct uses_allocator<::function<R(Args...)>, Alloc> : true_type {};
}
一个例子:
void func(int) {}
void func(char) {}
int main() {
// std::function<void(int)> f = func; // construction not OK
// f = func; // assignment not OK
function<void(int)> f = func; // construction OK
f = func; // assignment OK
}