#include <iostream>
#include <thread>
#include <utility>
using namespace std;
template <typename T>
class OnExitImpl : private T
{
public:
template <typename Y>
OnExitImpl(Y&& todo) : T(std::forward<Y>(todo)), _doIt(true) {}
OnExitImpl(OnExitImpl&& other) : T(std::move(static_cast<T&>(other))), _doIt(other._doIt)
{
other._doIt = false;
}
~OnExitImpl()
{
if (_doIt)
{
(*this)();
}
}
void Cancel()
{
_doIt = false;
}
OnExitImpl& operator=(OnExitImpl&& other)
{
this->T::operator=(std::move(static_cast<T&>(other)));
_doIt = other._doIt;
other._doIt = false;
}
private:
bool _doIt;
};
template <typename T>
OnExitImpl<T> OnExit(T action)
{
return OnExitImpl<T>(std::move(action));
}
int FetchMultithreaded(int stmt)
{
auto onExit = OnExit([&](){ cout << stmt << endl; });
std::thread fetchThread([&]()
{
auto onExit = OnExit([&](){ cout << stmt << endl; });
});
return 0;
}
int main()
{
return FetchMultithreaded(0);
}
在Visual Studio 2013中进行编译时,出现以下错误:
1>Source.cpp(9): error C2516: 'T' : is not a legal base class
1> Source.cpp(55) : see declaration of 'T'
1> Source.cpp(55) : see reference to class template instantiation 'OnExitImpl<void (__cdecl *)(void)>' being compiled
当我在http://ideone.com/O6I9nj上尝试使用它时,我仅收到有关std :: forward的大量错误,不确定那里发生了什么。虽然不确定正在使用哪个编译器。
Visual Studio错误消息让我认为这是一个编译器错误,因为它似乎将lambda视为函数指针...
编辑:将模板参数添加到std :: forward之后,它现在可以在Ideone上编译(但由于其他原因无法链接),但对于Visual Studio则不做任何更改。这使我怀疑这是一个编译器错误。
编辑2:无论如何,我通过添加以下代码来解决此问题:
template <typename Ret>
struct FnPtrWrapper
{
FnPtrWrapper(Ret (*fn)(void)) : _fn(fn)
{
assert(fn);
}
Ret operator()() const
{
return (*_fn)();
}
private:
Ret (*_fn)(void);
};
template <typename Ret>
OnExitImpl<FnPtrWrapper<Ret>> OnExit(Ret(*fn)(void))
{
return OnExitImpl<FnPtrWrapper<Ret>>(fn);
}
修复它似乎很奇怪,因为我使用的lambda触发了错误,实际上捕获了函数参数,因此不应转换为函数指针...
我相信这是一个VC ++错误,以前(在SO上)遇到过。最小的复制样本:
#include <type_traits>
template <typename T>
struct B { static_assert(std::is_class<T>::value, "T not a class"); }; // (2)
int main()
{
[]{
auto a = []{};
static_assert( std::is_class<decltype(a)>::value, "Not a class" ); // (1)
B<decltype(a)> b;
}();
}
请注意,代码必须位于外部lambda内部才能发生错误。
当(1)成功时,b
导致(2)失败的声明以
source_file.cpp(4):错误C2338:T不是类
source_file.cpp(11):请参见对B<void (__cdecl *)(void)>
正在编译的类模板' '的引用
这表示模板参数decltype(a)
表示函数的指针类型,同时也表示类的类型。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句