Overloading the function template

How can I overload the cb function template so that the code will compile? Now the exception is:

error C2535: void notify_property <T> :: cb (const F &): member function already defined or declared

But the templates are different.

template <typename T>
class notify_property {
public:
    virtual ~notify_property() {}

    //1
    template <typename F, typename = std::enable_if_t<std::is_void_v<std::invoke_result_t<std::decay_t<F>>>>>
    void cb(const F& task)
    {
        set_cb([task]
            {
                try { task(); }
                catch (...) {}
            });
    }
    //2
    template <typename F, typename = std::enable_if_t<std::is_void_v<std::invoke_result_t<std::decay_t<F>, std::decay_t<T>>>>>
    void cb(const F& task)
    {
        set_cb([this, task]
            {
                try { task(_value); }
                catch (...) {}
            });
    }
    //3
    template <typename F, typename... A, typename = std::enable_if_t<std::is_void_v<std::invoke_result_t<std::decay_t<F>, std::decay_t<T>, std::decay_t<A>...>>>>
    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;
};

Аnswer:

//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)
        {...}

        //2
        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)
        {...}

Upvotes: 3

Views: 109

Answers (2)

In my opinion this is happening due to same parameters in function 1 and function 2.

The solution for this is pretty simple. Changing the parameters in one of the 2 functions works just fine. Just add a parameter on function 2 (or 1) of the type int. While calling it just pass 0 as an argument. If it doesn't work then do comment down below :)

(I don't have so much reputation yet so I can't comment. So I answered instead :) )

Upvotes: 0

Drew Dormann
Drew Dormann

Reputation: 63947

typename = std::enable_if_t is problematic if duplicated because - as your error mentions - you're defining the same function multiple times, merely with a different default parameter.

Change every type template parameter

 // Type parameter, with a defaulted type
    typename = std::enable_if_t< ... >
 // ^^^^^^^^^^^ remove!

to a non-type template parameter that is part of the function's signature:

 // Value (pointer) parameter, with a defaulted value
    std::enable_if_t< ... >* = nullptr
 //                        ^^^^^^^^^^^ add

(Or, as cppreference does it)

 // Value (bool) parameter, with a defaulted value
    std::enable_if_t< ..., bool> = true
 //                      ^^^^^^^^^^^^^^ add

Upvotes: 4

Related Questions