使用void复制和交换成语显式模板类会产生错误

时间:2015-12-24 13:14:11

标签: c++ templates

给定模板类Foo<T>

template<class T>
class Foo
{
    public:
        friend void swap(Foo<T> &aFirst, Foo<T> &aSecond)
        {
            using std::swap;

            ...
        }
 }

显式模板类Foo<void>

template<>
class Foo<void>
{
    public:
        friend void swap(Foo<void> &aFirst, Foo<void> &aSecond)
        {
            using std::swap;

            ...
        }
 }

在显式模板类swap中使用Foo<void>函数时,我的编译器(MSVS 2015)会生成以下错误:

  

多个函数“swap”的实例与参数列表匹配

有什么方法可以解决这个问题吗?我需要明确定义void变体,因为需要有不同的行为。

修改

使用示例:

Foo(Foo<void> &&aOther) noexcept :
    Foo{}
{
    swap(*this, aOther);
}

编辑2

完整的课程来源:

template<class T>
class Future
{
    MARK_UNCOPYABLE(Future<T>)

    public:
        Future() :
            mMutex{},
            mDoneCondition{},
            mDone{ false },
            mCancelled{ false },
            mValue{}
        {

        }

        Future(Future<T> &&aOther) noexcept :
            Future{}
        {
            swap(*this, aOther);
        }

        virtual ~Future() = 0;

        Future<T> &operator=(Future<T> &&aOther) noexcept
        {
            swap(*this, aOther);

            return (*this);
        }

        virtual bool cancel()
        {
            bool cancelPending = false;

            {
                std::lock_guard<std::mutex> lock{ this->mMutex };

                if (!this->mDone && !this->mCancelled)
                {
                    this->mCancelled = true;
                    cancelPending = true;
                }
            }

            bool result = false;

            if (cancelPending)
            {
                handleCancel();

                {
                    std::lock_guard<std::mutex> lock{ this->mMutex };

                    this->mDoneCondition.notify_all();

                    result = !this->mDone;
                }
            }

            return result;
        }

        bool getValue(T &aOutValue)
        {
            std::unique_lock<std::mutex> lock{ this->mMutex };

            while (!this->mDone && !this->mCancelled)
            {
                this->mDoneCondition.wait(lock);
            }

            if (this->mDone)
            {
                aOutValue = this->mValue;
            }

            return this->mDone;
        }

        template<class Rep, class Period>
        bool getValueFor(T &aOutValue, const std::chrono::duration<Rep, Period> &aTimeoutDuration)
        {
            std::unique_lock<std::mutex> lock{ this->mMutex };

            bool waiting = true;
            while (!this->mDone && !this->mCancelled && waiting)
            {
                waiting = this->mDoneCondition.wait_for(lock, aTimeoutDuration);
            }

            if (this->mDone)
            {
                aOutValue = this->mValue;
            }

            return this->mDone;
        }

        template<class Clock, class Duration>
        bool getValueUntil(T &aOutValue, const std::chrono::time_point<Clock, Duration> &aTimeoutTime)
        {
            std::unique_lock<std::mutex> lock{ this->mMutex };

            bool waiting = true;
            while (!this->mDone && !this->mCancelled && waiting)
            {
                waiting = this->mDoneCondition.wait_until(lock, aTimeoutTime);
            }

            if (this->mDone)
            {
                aOutValue = this->mValue;
            }

            return this->mDone;
        }

        void setValue(const T &aValue)
        {
            std::lock_guard<std::mutex> lock{ this->mMutex };

            if (this->mDone)
            {
                throw std::runtime_error("Value already set");
            }

            this->mValue = aValue;
            this->mDone = true;

            this->mDoneCondition.notify_all();
        }

        inline void setValue(T &&aValue)
        {
            setValue(std::forward<T>(aValue));
        }

        inline bool isCancelled() const
        {
            return this->mCancelled;
        }

        inline bool isDone() const
        {
            return this->mDone;
        }

        friend void swap(Future<T> &aFirst, Future<T> &aSecond)
        {
            std::unique_lock<std::mutex> lock1(aFirst.mMutex, std::defer_lock);
            std::unique_lock<std::mutex> lock2(aSecond.mMutex, std::defer_lock);

            try
            {
                std::lock(lock1, lock2);

                using std::swap;

                aFirst.mDone = aSecond.mDone.load();
                aFirst.mCancelled = aSecond.mCancelled.load();
                swap(aFirst.mValue, aSecond.mValue)
            }
            catch (std::system_error)
            {
                // Do nothing
            }
        }

    protected:
        virtual void handleCancel() = 0;

    private:
        std::mutex mMutex;
        std::condition_variable mDoneCondition;
        std::atomic<bool> mDone;
        std::atomic<bool> mCancelled;
        T mValue;
};

template<class T>
Future<T>::~Future() = default;

template<>
class Future<void>
{
    MARK_UNCOPYABLE(Future)

    public:
        Future() :
            mMutex{},
            mDoneCondition{},
            mDone{ false },
            mCancelled{ false }
        {

        }

        Future(Future<void> &&aOther) noexcept :
            Future{}
        {
            swap(*this, aOther);
        }

        virtual ~Future() = 0;

        Future<void> &operator=(Future<void> &&aOther) noexcept
        {
            swap(*this, aOther);

            return (*this);
        }

        virtual bool cancel()
        {
            bool cancelPending = false;

            {
                std::lock_guard<std::mutex> lock{ this->mMutex };

                if (!this->mDone && !this->mCancelled)
                {
                    this->mCancelled = true;
                    cancelPending = true;
                }
            }

            bool result = false;

            if (cancelPending)
            {
                handleCancel();

                {
                    std::lock_guard<std::mutex> lock{ this->mMutex };

                    this->mDoneCondition.notify_all();

                    result = !this->mDone;
                }
            }

            return result;
        }

        bool getValue()
        {
            std::unique_lock<std::mutex> lock{ this->mMutex };

            while (!this->mDone && !this->mCancelled)
            {
                this->mDoneCondition.wait(lock);
            }

            return this->mDone;
        }

        template<class Rep, class Period>
        bool getValueFor(const std::chrono::duration<Rep, Period> &aTimeoutDuration)
        {
            std::unique_lock<std::mutex> lock{ this->mMutex };

            bool waiting = true;
            while (!this->mDone && !this->mCancelled && waiting)
            {
                waiting = this->mDoneCondition.wait_for(lock, aTimeoutDuration);
            }

            return this->mDone;
        }

        template<class Clock, class Duration>
        bool getValueUntil(const std::chrono::time_point<Clock, Duration> &aTimeoutTime)
        {
            std::unique_lock<std::mutex> lock{ this->mMutex };

            bool waiting = true;
            while (!this->mDone && !this->mCancelled && waiting)
            {
                waiting = this->mDoneCondition.wait_until(lock, aTimeoutTime);
            }

            return this->mDone;
        }

        void setValue()
        {
            std::lock_guard<std::mutex> lock{ this->mMutex };

            if (this->mDone)
            {
                throw std::runtime_error("Value already set");
            }

            this->mDone = true;

            this->mDoneCondition.notify_all();
        }

        inline bool isCancelled() const
        {
            return this->mCancelled;
        }

        inline bool isDone() const
        {
            return this->mDone;
        }

        friend void swap(Future<void> &aFirst, Future<void> &aSecond) noexcept
        {
            std::unique_lock<std::mutex> lock1(aFirst.mMutex, std::defer_lock);
            std::unique_lock<std::mutex> lock2(aSecond.mMutex, std::defer_lock);

            try
            {
                std::lock(lock1, lock2);

                using std::swap;

                aFirst.mDone = aSecond.mDone.load();
                aFirst.mCancelled = aSecond.mCancelled.load();
            }
            catch (std::system_error)
            {
                // Do nothing
            }
        }

    protected:
        virtual void handleCancel() = 0;

    private:
        std::mutex mMutex;
        std::condition_variable mDoneCondition;
        std::atomic<bool> mDone;
        std::atomic<bool> mCancelled;
};

0 个答案:

没有答案