Visual C ++ 2015 std :: function vs C2893

时间:2016-01-15 22:01:00

标签: c++ templates c++11 visual-studio-2015 std-function

所以我正在尝试使用std :: function和templates,并在下面提供了代码。不幸的是,它在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>
        ]

1 个答案:

答案 0 :(得分:2)

MockBlock0::NextHandler又名Block<MockBlock1>::NextHandler

它是std::function<void (Block<MockBlock1>&, MockBlock1&)>

可以使用[](MockBlock0& b0, MockBlock1& b1) { /* stuff */ }类型的左值调用Block<MockBlock1>吗?它不能,因为并非所有Block<MockBlock1>都是MockBlock0 s。

因此错误。