erro: uso de função excluída

121

Tenho trabalhado em alguns códigos C ++ que um amigo escreveu e recebo o seguinte erro que nunca vi antes ao compilar com gcc4.6:

error: use of deleted function

GameFSM_<std::array<C, 2ul> >::hdealt::hdealt()’ is implicitly deleted because the default definition would be ill-formed:
uninitialized non-static const member const h_t FlopPokerGameFSM_<std::array<C, 2ul> >::hdealt::h

Edit: Isso vem de uma parte do código usando boost MSM: Boost Webpage

Edit2: Não é = delete()usado em nenhum lugar no código-fonte.

De modo geral, o que significa esse erro? O que devo procurar quando esse tipo de erro ocorrer?

transporte 87
fonte
4
e o código que você está compilando?
ColWhi
Eu estava mais apenas me perguntando o que significava o erro? Eu preciso postar o código para isso também?
translado 87 de
1
gcc.gnu.org/bugzilla/show_bug.cgi?id=47417 pode ajudar, você também está usando boost?
ColWhi
@Sasquiha, sim, estou usando boost MSM.
translado 87 de
20
Já que isso surge como a primeira correspondência do Google para esse tipo de erro - não é o caso aqui, mas a causa mais comum para esse tipo de erro é depois que você adicionou algum construtor personalizado a uma classe - como resultado, o compilador para de criar o construtor padrão , e se uma instância da classe for criada por meio do construtor padrão, este erro aparecerá. Basta adicionar o construtor padrão explicitamente.
SF.

Respostas:

170

A mensagem de erro diz claramente que o construtor padrão foi excluído implicitamente . Ele até diz o porquê: a classe contém uma variável const não estática, que não seria inicializada pelo ctor padrão.

class X {
    const int x;
};

Desde X::xé const, ele deve ser inicializado - mas um ctor padrão normalmente não inicializá-lo (porque é um tipo POD). Portanto, para obter um ctor padrão, você precisa definir um (e ele deve inicializar x). Você pode ter o mesmo tipo de situação com um membro que é uma referência:

class X { 
    whatever &x;
};

Provavelmente, vale a pena notar que ambos também desabilitarão a criação implícita de um operador de atribuição, essencialmente pelo mesmo motivo. O operador de atribuição implícita normalmente faz a atribuição de membros, mas com um membro const ou membro de referência, ele não pode fazer isso porque o membro não pode ser atribuído. Para fazer a atribuição funcionar, você precisa escrever seu próprio operador de atribuição.

É por isso que um constmembro normalmente deve ser estático - quando você faz uma atribuição, você não pode atribuir o membro const de qualquer maneira. Em um caso típico, todas as suas instâncias terão o mesmo valor, então elas também podem compartilhar o acesso a uma única variável em vez de ter muitas cópias de uma variável que terá o mesmo valor.

É possível, claro, criar instâncias com valores diferentes - você (por exemplo) passa um valor ao criar o objeto, então dois objetos diferentes podem ter dois valores diferentes. Se, entretanto, você tentar fazer algo como trocá-los, o membro const manterá seu valor original em vez de ser trocado.

Jerry Coffin
fonte
@Jeffry Coffin: A mensagem de erro real foi postada como uma edição, a mensagem de erro inicial postada foi apenasC++ error: use of deleted function
Alok Save
1
@Als: Desculpe, provavelmente eu deveria ter sido explícito que não pretendia isso como um insulto ou qualquer coisa dessa ordem, apenas que o que estava disponível no momento tornava aparente que essas respostas não estavam certas.
Jerry Coffin
Sem problemas, eu não queria ser inflexível ... Sua resposta é fantástica e explica melhor a situação. +1 de mim :)
Alok Save
Suponho que você possa me ajudar com meu problema aqui, por favor: stackoverflow.com/questions/23349524/…
Saher Ahwal
2
@OllieFord: Depende. O que deve acontecer se (por exemplo) você atribuir um objeto com um valor nesse campo a outro que tem um valor diferente nesse campo? Se for substituído, não pode ser constante. Se isso não deveria ser permitido, então o valor pode realmente ser parte do tipo (por exemplo, um parâmetro de modelo, se conhecido em tempo de compilação).
Jerry Coffin
11

Você está usando uma função marcada como deleted.
Por exemplo:

int doSomething( int ) = delete;

O = delete é um novo recurso do C ++ 0x. Isso significa que o compilador deve parar imediatamente de compilar e reclamar "esta função foi excluída" assim que o usuário usar essa função.

Se você vir esse erro, deve verificar a declaração da função para =delete.

Para saber mais sobre este novo recurso introduzido em C ++ 0x, verifique isto .

Alok Save
fonte
7
Por curiosidade, quando fazer algo assim seria útil?
Pepe de
@Peter: para evitar conversões implícitas.
R. Martinho Fernandes
7
Na verdade, diz "excluído implicitamente porque ..." , o exemplo acima seria explícito.
Georg Fritzsche
@Peter R: parece que este é um exemplo: en.wikipedia.org/wiki/…
shuttle87
1
@Downvoter: A mensagem de erro real foi postada como uma edição, a mensagem de erro inicial postada era apenasC++ error: use of deleted function
Alok Save
4

gcc 4.6 suporta um novo recurso de funções excluídas, onde você pode escrever

hdealt() = delete;

para desativar o construtor padrão.

Aqui, o compilador obviamente viu que um construtor padrão não pode ser gerado e =deleteo fez para você.

Bo Persson
fonte
2

Encontrei esse erro ao herdar de uma classe abstrata e não implementar todos os métodos virtuais puros em minha subclasse.

Christopher
fonte
1
Da mesma forma, obtive o mesmo derivando public virtualde uma classe base de 2º nível, onde a classe base de 1º nível tinha um construtor padrão explicitamente excluído. A remoção virtualcorrigiu o problema sem a necessidade de implementar todos os métodos.
Maitre Bart
1

No padrão C ++ 0x atual, você pode desabilitar explicitamente os construtores padrão com a sintaxe de exclusão, por exemplo

MyClass() = delete;

Gcc 4.6 é a primeira versão a suportar esta sintaxe, então talvez seja esse o problema ...

Jarmond
fonte
Gcc 4.6 is the first version to support this syntaxAcho que isso explicaria por que nunca o vi antes, pois comecei a usar o gcc4.6 recentemente.
translado 87 de
2
Tenho usado essa sintaxe com o GCC 4.5 há anos. Quero dizer dias.
R. Martinho Fernandes
Ah, devo ter pensado em ctors delegados que estão no GCC 4.6.
jarmond de
1

Mudar do gcc 4.6 para o gcc 4.8 resolveu isso para mim.

Michael Bosworth
fonte