给定模板类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;
};