2014-12-07 6 views
1

이 코드는 VC2013 구축하는 데 실패 : (편집 : 그것은 빌드 실패 이유를 묻는 게 아니에요) 오류와실패 :: 기능 <> &

#include <functional> 

struct MyStruct 
{ 
    std::function<void()> m_Func; 
    MyStruct(const std::function<void()>& func) : m_Func(func) {} 
}; 


int main() 
{ 
    MyStruct rc(NULL); 
    return 0; 
} 

:

1>c:\program files (x86)\microsoft visual studio 12.0\vc\include\xrefwrap(283): error C2064: term does not evaluate to a function taking 0 arguments 
1>   c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(228) : see reference to function template instantiation '_Ret std::_Callable_obj<int,false>::_ApplyX<_Rx,>(void)' being compiled 
1>   with 
1>   [ 
1>    _Ret=void 
1> ,   _Rx=void 
1>   ] 
1>   c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(228) : see reference to function template instantiation '_Ret std::_Callable_obj<int,false>::_ApplyX<_Rx,>(void)' being compiled 
1>   with 
1>   [ 
1>    _Ret=void 
1> ,   _Rx=void 
1>   ] 
1>   c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(226) : while compiling class template member function 'void std::_Func_impl<_MyWrapper,_Alloc,_Ret,>::_Do_call(void)' 
1>   with 
1>   [ 
1>    _Alloc=std::allocator<std::_Func_class<void,>> 
1> ,   _Ret=void 
1>   ] 
1>   c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(495) : see reference to class template instantiation 'std::_Func_impl<_MyWrapper,_Alloc,_Ret,>' being compiled 
1>   with 
1>   [ 
1>    _Alloc=std::allocator<std::_Func_class<void,>> 
1> ,   _Ret=void 
1>   ] 
1>   c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(396) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Do_alloc<_Myimpl,_Ty,_Alloc>(_Fty &&,_Alloc)' being compiled 
1>   with 
1>   [ 
1>    _Ret=void 
1> ,   _Ty=int 
1> ,   _Alloc=std::allocator<std::_Func_class<void,>> 
1> ,   _Fty=int 
1>   ] 
1>   c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(396) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Do_alloc<_Myimpl,_Ty,_Alloc>(_Fty &&,_Alloc)' being compiled 
1>   with 
1>   [ 
1>    _Ret=void 
1> ,   _Ty=int 
1> ,   _Alloc=std::allocator<std::_Func_class<void,>> 
1> ,   _Fty=int 
1>   ] 
1>   c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(385) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Reset_alloc<_Ty,std::allocator<std::_Func_class<_Ret,>>>(_Fty &&,_Alloc)' being compiled 
1>   with 
1>   [ 
1>    _Ret=void 
1> ,   _Ty=int 
1> ,   _Fty=int 
1> ,   _Alloc=std::allocator<std::_Func_class<void,>> 
1>   ] 
1>   c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(385) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Reset_alloc<_Ty,std::allocator<std::_Func_class<_Ret,>>>(_Fty &&,_Alloc)' being compiled 
1>   with 
1>   [ 
1>    _Ret=void 
1> ,   _Ty=int 
1> ,   _Fty=int 
1> ,   _Alloc=std::allocator<std::_Func_class<void,>> 
1>   ] 
1>   c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(671) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Reset<_Ty>(_Fty &&)' being compiled 
1>   with 
1>   [ 
1>    _Ret=void 
1> ,   _Ty=int 
1> ,   _Fty=int 
1>   ] 
1>   c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(671) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Reset<_Ty>(_Fty &&)' being compiled 
1>   with 
1>   [ 
1>    _Ret=void 
1> ,   _Ty=int 
1> ,   _Fty=int 
1>   ] 
1>   f:\work\teststdfunction\teststdfunction.cpp(16) : see reference to function template instantiation 'std::function<void (void)>::function<int>(_Fx &&)' being compiled 
1>   with 
1>   [ 
1>    _Fx=int 
1>   ] 
1>   f:\work\teststdfunction\teststdfunction.cpp(16) : see reference to function template instantiation 'std::function<void (void)>::function<int>(_Fx &&)' being compiled 
1>   with 
1>   [ 
1>    _Fx=int 
1>   ] 

(마지막 두 개의보고 된 오류에서 '_Fx = int'에 유의하십시오.)

MyStruct rc(NULL)에서 MyStruct rc(nullptr)으로 변경하면 오류가 해결되므로 함께 살 수 있습니다. 지금

1>f:\work\main\dev\common\teststdfunction\teststdfunction\teststdfunction.cpp(16): error C2664: 'MyStruct::MyStruct(const MyStruct &)' : cannot convert argument 1 from 'int' to 'std::function &'

원래 오류보다 더 많은 의미가

하고 NULL을 고정 : MyStruct(std::function<void()>& func)은 매우, 매우 다른 오류를 제공 (

1) MYSTRUCT의의 ctor에서 const를 한정자를 제거 : 두 가지 그러나 신비 남아 그것을 해결하지 않습니다 을 nullptr 할 수 있습니다. 왜 INT (또는 nullptr)는 std::function<>& 캐스팅을 거부하지만, 원래의 코드를 컴파일하고 VS2010에서 예상대로 작동)을 const std::function<>&?

2에 캐스팅 동의 않습니다. 애매한 VS2010 라이브러리 버그입니까?


편집 : 는 지금까지 CONST/비 const를 질문은 간다, 지금 주조 참여하고 잠재적 인 유형 불일치 아마 빨간 청어 생각합니다. 전달 된 인수 - NULL 또는 nullptr -은 리터럴이므로 const입니다. 그냥 const가 아닌 참조에 바인딩 할 수 없습니다. 예 :

const int& a = 8; // Ok 
int& b = 9; // error C2440: 'initializing' : cannot convert from 'int' to 'int &' 

맞습니까? 나는 아직도 뭔가를 놓치고 있습니까?

+1

'nullptr'은'nullptr_t' 타입의 값으로,'std :: function'의 생성자가 받아 들일 수 있습니다. 'NULL'은 반드시'nullptr'로 정의되는 것은 아니며 다른 값이 될 수도 있습니다. NULL이 아닌'nullptr'을 사용하십시오. –

+1

언급 한대로, 나는 nullptr로 변경했습니다. 원래 코드가 컴파일되지 않은 이유를 묻지 않습니다. –

+1

리터럴은 완전히 다릅니다. 그들은 rvalues입니다. 이것은 완전히 다른 것입니다. 그 잘못된 신화를 전파하지 마십시오. – Puppy

답변

1

약간이 점에 버그가되고 캐스트를 허용했다.

nullptr이 작동하는 이유는 std::function이 특정 생성자를 가지고 있기 때문입니다. 이 생성자는 함수 템플리트가 낮은 기본 설정으로 순위 지 정되고 나머지는 모두 동일하므로 항상 해당 인수에 가장 잘 일치합니다.

일반적으로 0은 암시 적으로 nullptr으로 변환됩니다. 문제는 을 함수 객체로 구성되는 제약되지 않은 함수 템플릿 생성자로 전달할 수 있다는 것입니다. 여기에는 암시 적 변환이 필요하지 않으므로 모두 같지 않으므로 int이 유효한 함수 객체가 아니라는 오류가 발생합니다.

libstdC++ 및 libC++은 생성자를 제한하는이 문제에 대한 C++ 14 수정을 구현했기 때문에 이러한 동작을 나타내지 않습니다. C++ 11에서는이 동작이 C++ 11 구현에 적합하지 않습니다.

이런 종류의 문제는 NULL이 사용해서는 안되는 끔찍한 이유입니다. 사실, VS2010 팀은 NULL이 C++의 다른 모든 기능과 너무 심하게 상호 작용하고 C++ 11과 특히 상호 작용하기 때문에 마지막 순간에 추가 기능으로 nullptr을 문 밖으로 내 보내야했습니다.

const 대 0-참고 자료에 대해서는 다른 답변을 통해 해당 문제를 적절하게 설명 할 수 있습니다.

은 C++에서 제공되는 제약 생성자 수정없이 std::function를 사용할 때 찾을 수있는 다른 WTFs 있습니다 14-이 유일한 아니다. 길고 짧다는 것은 C++ 11 표준의 결함이며, VS의 이 아닙니다. VS2010 컴파일러는 아마도 컴파일러 과부하 해결 버그 일 것입니다.

+0

답변 해 주셔서 감사합니다. 아직도 이해할 수없는 것은 SFINAE가 시작되지 않는 이유입니다. 0이 제한되지 않은 템플릿과 일치했지만 나중에는 실패했습니다. nullptr_t 전문화가 다음에 일치해야합니까? –

+0

@Ofek : SFINAE는 함수 시그니처에만 적용됩니다. 그것은 일반적으로 신체에 적용되지 않습니다. – Puppy

0

캐스팅 a T에서 U&까지는 결코 작동하지 않으며 의도적으로 작동합니다. U const&으로 전송할 수 있습니다. 그 이유는 임시 U 개체의 변경 사항이 T 값으로 다시 전파되지 않기 때문입니다.

VS2010 여기에 특수 생성자 템플릿 제약과 다른 암시 적 변환과 관련이있다 (그러나 적절한 설정으로, 그것에 대해 경고합니다)

+0

잘 모르겠습니다. 분명히 void f (int & i)는 int를 받아 들일 수 있습니다. T에서 U &로 캐스팅하는 것으로 한정되지 않습니다. –

+0

@OfekShilon : 아니요, 할 수 없습니다 :'4'가 명백한'int' 임에도 불구하고'f (4)'는 거부됩니다. 그리고 그것은 단지'T'에서'T &'까지입니다 - 당신은'4'도 변경할 수 없습니다. – MSalters

+0

은 4 * const * int가 아닙니다. AFAIK 4를 int에 바인딩하지 못하면 &는 double입니다 : (a) const이고, (b)는 rvalue입니다. –

관련 문제