Visual C++ 2015 std::function 与 C2893
Visual C++ 2015 std::function vs C2893
所以我正在试验 std::function 和模板,并想出了下面的代码。不幸的是,它在 Visual Studio 2015 上导致了 C2893(也许它在其他编译器上工作正常?)。我不知道这是否有帮助,但是当我用 void* 替换 NextHandler 的第一个参数时,编译错误消失了...
#include <functional>
template<typename T>
class Block
{
public:
typedef Block CurrentBlock;
typedef T NextBlock;
typedef std::function<void (CurrentBlock& currentBlock,
NextBlock& nextBlock)>
NextHandler;
private:
NextBlock* _nextBlock;
NextHandler _nextHandler;
protected:
virtual void
doProcess() = 0;
public:
NextBlock&
next(NextBlock& nextBlock, NextHandler handler)
{
_nextBlock = &nextBlock;
_nextHandler = handler;
return nextBlock;
}
void
process()
{
doProcess();
_nextHandler(*this, *_nextBlock);
_nextBlock->process();
}
};
template<>
class Block<void>
{
protected:
virtual void
doProcess() = 0;
public:
void
process()
{
doProcess();
}
};
class MockBlock1 : public Block<void>
{
public:
void
doProcess() override
{
}
};
class MockBlock0 : public Block<MockBlock1>
{
public:
void
doProcess() override
{
}
};
void someFunction()
{
MockBlock0 b0;
MockBlock1 b1;
b0.next(b1, [](MockBlock0& b0, MockBlock1& b1)
{
});
}
完整的错误信息是:
c:\program files (x86)\microsoft visual studio 14.0\vc\include\type_traits(1494): error C2893: Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Types &&...)'
c:\program files (x86)\microsoft visual studio 14.0\vc\include\type_traits(1494): note: With the following template arguments:
c:\program files (x86)\microsoft visual studio 14.0\vc\include\type_traits(1494): note: '_Callable=_Decayed &'
c:\program files (x86)\microsoft visual studio 14.0\vc\include\type_traits(1494): note: '_Types={Block<MockBlock1> &, MockBlock1 &}'
c:\program files (x86)\microsoft visual studio 14.0\vc\include\functional(210): note: see reference to function template instantiation 'void std::_Invoke_ret<_Rx,_Callable&,Block<MockBlock1>&,MockBlock1&>(std::_Forced<_Rx,true>,_Callable &,Block<MockBlock1> &,MockBlock1 &)' being compiled
with
[
_Rx=void,
_Callable=_Decayed
]
c:\program files (x86)\microsoft visual studio 14.0\vc\include\functional(208): note: while compiling class template member function 'void std::_Func_impl<_Decayed,_Alloc,_Ret,Block<MockBlock1> &,MockBlock1 &>::_Do_call(Block<MockBlock1> &,MockBlock1 &)'
with
[
_Alloc=std::allocator<int>,
_Ret=void
]
c:\program files (x86)\microsoft visual studio 14.0\vc\include\functional(136): note: see reference to class template instantiation 'std::_Func_impl<_Decayed,_Alloc,_Ret,Block<MockBlock1> &,MockBlock1 &>' being compiled
with
[
_Alloc=std::allocator<int>,
_Ret=void
]
c:\program files (x86)\microsoft visual studio 14.0\vc\include\functional(339): note: see reference to class template instantiation 'std::_Is_large<_Myimpl>' being compiled
c:\program files (x86)\microsoft visual studio 14.0\vc\include\functional(318): note: see reference to function template instantiation 'void std::_Func_class<_Ret,Block<MockBlock1> &,MockBlock1 &>::_Reset_alloc<_Ty,std::allocator<int>>(_Fx &&,const _Alloc &)' being compiled
with
[
_Ret=void,
_Ty=someFunction::<lambda_3b7d9d95683ccbaabd52b19687773e09>,
_Fx=someFunction::<lambda_3b7d9d95683ccbaabd52b19687773e09>,
_Alloc=std::allocator<int>
]
c:\program files (x86)\microsoft visual studio 14.0\vc\include\functional(318): note: see reference to function template instantiation 'void std::_Func_class<_Ret,Block<MockBlock1> &,MockBlock1 &>::_Reset_alloc<_Ty,std::allocator<int>>(_Fx &&,const _Alloc &)' being compiled
with
[
_Ret=void,
_Ty=someFunction::<lambda_3b7d9d95683ccbaabd52b19687773e09>,
_Fx=someFunction::<lambda_3b7d9d95683ccbaabd52b19687773e09>,
_Alloc=std::allocator<int>
]
c:\program files (x86)\microsoft visual studio 14.0\vc\include\functional(484): note: see reference to function template instantiation 'void std::_Func_class<_Ret,Block<MockBlock1> &,MockBlock1 &>::_Reset<someFunction::<lambda_3b7d9d95683ccbaabd52b19687773e09>>(_Fx &&)' being compiled
with
[
_Ret=void,
_Fx=someFunction::<lambda_3b7d9d95683ccbaabd52b19687773e09>
]
c:\program files (x86)\microsoft visual studio 14.0\vc\include\functional(484): note: see reference to function template instantiation 'void std::_Func_class<_Ret,Block<MockBlock1> &,MockBlock1 &>::_Reset<someFunction::<lambda_3b7d9d95683ccbaabd52b19687773e09>>(_Fx &&)' being compiled
with
[
_Ret=void,
_Fx=someFunction::<lambda_3b7d9d95683ccbaabd52b19687773e09>
]
c:\test\blocks.cpp(88): note: see reference to function template instantiation 'std::function<void (Block<MockBlock1> &,MockBlock1 &)>::function<someFunction::<lambda_3b7d9d95683ccbaabd52b19687773e09>>(_Fx)' being compiled
with
[
_Fx=someFunction::<lambda_3b7d9d95683ccbaabd52b19687773e09>
]
c:\test\blocks.cpp(88): note: see reference to function template instantiation 'std::function<void (Block<MockBlock1> &,MockBlock1 &)>::function<someFunction::<lambda_3b7d9d95683ccbaabd52b19687773e09>>(_Fx)' being compiled
with
[
_Fx=someFunction::<lambda_3b7d9d95683ccbaabd52b19687773e09>
]
MockBlock0::NextHandler
又名 Block<MockBlock1>::NextHandler
是什么?
是std::function<void (Block<MockBlock1>&, MockBlock1&)>
。
是否可以使用 Block<MockBlock1>
类型的任何左值调用 [](MockBlock0& b0, MockBlock1& b1) { /* stuff */ }
?它不能,因为并非所有 Block<MockBlock1>
都是 MockBlock0
。
因此出现错误。
所以我正在试验 std::function 和模板,并想出了下面的代码。不幸的是,它在 Visual Studio 2015 上导致了 C2893(也许它在其他编译器上工作正常?)。我不知道这是否有帮助,但是当我用 void* 替换 NextHandler 的第一个参数时,编译错误消失了...
#include <functional>
template<typename T>
class Block
{
public:
typedef Block CurrentBlock;
typedef T NextBlock;
typedef std::function<void (CurrentBlock& currentBlock,
NextBlock& nextBlock)>
NextHandler;
private:
NextBlock* _nextBlock;
NextHandler _nextHandler;
protected:
virtual void
doProcess() = 0;
public:
NextBlock&
next(NextBlock& nextBlock, NextHandler handler)
{
_nextBlock = &nextBlock;
_nextHandler = handler;
return nextBlock;
}
void
process()
{
doProcess();
_nextHandler(*this, *_nextBlock);
_nextBlock->process();
}
};
template<>
class Block<void>
{
protected:
virtual void
doProcess() = 0;
public:
void
process()
{
doProcess();
}
};
class MockBlock1 : public Block<void>
{
public:
void
doProcess() override
{
}
};
class MockBlock0 : public Block<MockBlock1>
{
public:
void
doProcess() override
{
}
};
void someFunction()
{
MockBlock0 b0;
MockBlock1 b1;
b0.next(b1, [](MockBlock0& b0, MockBlock1& b1)
{
});
}
完整的错误信息是:
c:\program files (x86)\microsoft visual studio 14.0\vc\include\type_traits(1494): error C2893: Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Types &&...)'
c:\program files (x86)\microsoft visual studio 14.0\vc\include\type_traits(1494): note: With the following template arguments:
c:\program files (x86)\microsoft visual studio 14.0\vc\include\type_traits(1494): note: '_Callable=_Decayed &'
c:\program files (x86)\microsoft visual studio 14.0\vc\include\type_traits(1494): note: '_Types={Block<MockBlock1> &, MockBlock1 &}'
c:\program files (x86)\microsoft visual studio 14.0\vc\include\functional(210): note: see reference to function template instantiation 'void std::_Invoke_ret<_Rx,_Callable&,Block<MockBlock1>&,MockBlock1&>(std::_Forced<_Rx,true>,_Callable &,Block<MockBlock1> &,MockBlock1 &)' being compiled
with
[
_Rx=void,
_Callable=_Decayed
]
c:\program files (x86)\microsoft visual studio 14.0\vc\include\functional(208): note: while compiling class template member function 'void std::_Func_impl<_Decayed,_Alloc,_Ret,Block<MockBlock1> &,MockBlock1 &>::_Do_call(Block<MockBlock1> &,MockBlock1 &)'
with
[
_Alloc=std::allocator<int>,
_Ret=void
]
c:\program files (x86)\microsoft visual studio 14.0\vc\include\functional(136): note: see reference to class template instantiation 'std::_Func_impl<_Decayed,_Alloc,_Ret,Block<MockBlock1> &,MockBlock1 &>' being compiled
with
[
_Alloc=std::allocator<int>,
_Ret=void
]
c:\program files (x86)\microsoft visual studio 14.0\vc\include\functional(339): note: see reference to class template instantiation 'std::_Is_large<_Myimpl>' being compiled
c:\program files (x86)\microsoft visual studio 14.0\vc\include\functional(318): note: see reference to function template instantiation 'void std::_Func_class<_Ret,Block<MockBlock1> &,MockBlock1 &>::_Reset_alloc<_Ty,std::allocator<int>>(_Fx &&,const _Alloc &)' being compiled
with
[
_Ret=void,
_Ty=someFunction::<lambda_3b7d9d95683ccbaabd52b19687773e09>,
_Fx=someFunction::<lambda_3b7d9d95683ccbaabd52b19687773e09>,
_Alloc=std::allocator<int>
]
c:\program files (x86)\microsoft visual studio 14.0\vc\include\functional(318): note: see reference to function template instantiation 'void std::_Func_class<_Ret,Block<MockBlock1> &,MockBlock1 &>::_Reset_alloc<_Ty,std::allocator<int>>(_Fx &&,const _Alloc &)' being compiled
with
[
_Ret=void,
_Ty=someFunction::<lambda_3b7d9d95683ccbaabd52b19687773e09>,
_Fx=someFunction::<lambda_3b7d9d95683ccbaabd52b19687773e09>,
_Alloc=std::allocator<int>
]
c:\program files (x86)\microsoft visual studio 14.0\vc\include\functional(484): note: see reference to function template instantiation 'void std::_Func_class<_Ret,Block<MockBlock1> &,MockBlock1 &>::_Reset<someFunction::<lambda_3b7d9d95683ccbaabd52b19687773e09>>(_Fx &&)' being compiled
with
[
_Ret=void,
_Fx=someFunction::<lambda_3b7d9d95683ccbaabd52b19687773e09>
]
c:\program files (x86)\microsoft visual studio 14.0\vc\include\functional(484): note: see reference to function template instantiation 'void std::_Func_class<_Ret,Block<MockBlock1> &,MockBlock1 &>::_Reset<someFunction::<lambda_3b7d9d95683ccbaabd52b19687773e09>>(_Fx &&)' being compiled
with
[
_Ret=void,
_Fx=someFunction::<lambda_3b7d9d95683ccbaabd52b19687773e09>
]
c:\test\blocks.cpp(88): note: see reference to function template instantiation 'std::function<void (Block<MockBlock1> &,MockBlock1 &)>::function<someFunction::<lambda_3b7d9d95683ccbaabd52b19687773e09>>(_Fx)' being compiled
with
[
_Fx=someFunction::<lambda_3b7d9d95683ccbaabd52b19687773e09>
]
c:\test\blocks.cpp(88): note: see reference to function template instantiation 'std::function<void (Block<MockBlock1> &,MockBlock1 &)>::function<someFunction::<lambda_3b7d9d95683ccbaabd52b19687773e09>>(_Fx)' being compiled
with
[
_Fx=someFunction::<lambda_3b7d9d95683ccbaabd52b19687773e09>
]
MockBlock0::NextHandler
又名 Block<MockBlock1>::NextHandler
是什么?
是std::function<void (Block<MockBlock1>&, MockBlock1&)>
。
是否可以使用 Block<MockBlock1>
类型的任何左值调用 [](MockBlock0& b0, MockBlock1& b1) { /* stuff */ }
?它不能,因为并非所有 Block<MockBlock1>
都是 MockBlock0
。
因此出现错误。