2016-11-17 5 views
1

나는 단지 호기심이 많다. 내가 서명const 및 매개 변수에서 & 매개 변수로의 변환이 잘못되었습니다.

CommandLogFilter::CommandLogFilter(QSharedPointer<LogServer> logServer, QObject *parent, 
         void (*preprocessValidCommand)(CommandDescriptor &descriptor)) 

와 g에서 오류가 발생하여 생성자에 세 번째 매개 변수로 서명

void printCommandReceived(const CommandDescriptor &descriptor) 

과 기능 포인터를 전달하고 ++ 컴파일러 : 나의 이해에서

error: invalid conversion from ‘void (*)(const CommandDescriptor&)’ to ‘void (*)(CommandDescriptor&)’ [-fpermissive] 

비에 대한 참조 -const 개체는 const 개체 매개 변수를 참조하는 인수로 사용할 수 있어야합니다. 따라서 비 const 객체 참조를 받아들이는 함수에 대한 타입 포인터를 가진 매개 변수는 심지어 const 객체 참조조차 받아들이는 함수에 대한 포인터 유형의 인수에 만족해야합니다 (그리고 암시 적 변환을 수행해야합니다).

어디서 잘못 되었나요?

+1

"무언가에 대한 포인터"가 있으며 "다른 포인터"를 전달하려고합니다. pointed-to 유형이 유사한 경우에도 암시 적 변환은 없습니다. –

답변

2

void (*)(const CommandDescriptor&)void (*)(CommandDescriptor&)은 서로 관련이없는 완전히 다른 두 가지 유형입니다.

const에 대한 매우 간단한 규칙이 있습니다 X*X**X const * const *로 변환 등등 할 수 X const*로 변환 할 수 있습니다. 참고 문헌과 같은 것. 그 밖의 것은 허용되지 않습니다.

X**과 같이 const을 임의의 위치에 임의로 추가하거나 제거 할 수없는 규칙은 X const **으로 변환 할 수 없습니다. 이것은 함수 인수의 위치에서도 마찬가지입니다. const을 추가하거나 제거하여 호환 유형을 얻을 수 없습니다.

귀하의 사례를 수용하고 일관성있게 유지되도록 이러한 규칙을 확장 할 수 있습니까? 아마 그렇게. 그러나 그들은 그렇지 않습니다.

1

C++에는 const이 암시 적으로 추가되거나 제거 될 수있는 제한된 상황이 있습니다. 당신은 할 수없는 곳으로 뛰어 들었습니다. 그 이유는 아마도 "안전하다고 생각되는 사례를 설명하는 것이 어려울 것이며 표준 작성자는 게으르고 보수적 인 사례"라고 간단히 말하면됩니다.

주위 작품으로, 당신은이 작업을 수행 할 수 있습니다

CommandLogFilter bob(
    logServer, 
    parent, 
    [](CommandDescriptor &descriptor) { 
    return printCommandReceived(descriptor); 
    } 
); 

무국적 람다 암시 적 변환-에 할 수있는 포인터 자신의 서명과 일치하는 기능.

나는 서명을 거기에 명시해야하는 것을 싫어하지만 템플릿 "자동"람다와 비슷한 것을 할 수없고 유감스럽게도 서명을 추론 할 방법이 없다.