Resposta curta: você está misturando conceitos antes do tempo de compilação e tempo de compilação que têm semelhanças em seus propósitos. As interfaces (classes abstratas e toda a implementação do paradigma de orientação a objetos) são forçadas no momento da compilação . Os conceitos são a mesma idéia, mas no contexto da programação genérica que ocorre em C ++ ANTES do tempo de compilação . Ainda não temos esse último recurso.
Mas deixe-me explicar desde o início.
Resposta longa:
De fato, os Conceitos são apenas aplicação de linguagem e "facilitado para o programador" de algo já presente na linguagem, que você poderia chamar de "digitação de pato".
Quando você passa um tipo para uma função de modelo, que é uma função genérica a partir da qual o compilador gera código real (em linha) quando chamado, esse tipo precisa ter algumas propriedades (características?) Que serão usadas no código do modelo. Portanto, é a idéia de digitar patos, mas tudo é gerado e feito em tempo de compilação .
O que acontece quando o tipo não possui as propriedades necessárias?
Bem, o compilador saberá que há um problema apenas quando o código gerado do modelo for compilado e falhar. Isso significa que o erro que será gerado será um erro dentro do código do modelo, que será mostrado ao programador como seu erro. Além disso, o erro terá toneladas de informações por causa das meta-informações fornecidas no caso de geração de código do modelo, para saber de qual instanciação do modelo estamos falando.
Vários problemas com isso: primeiro, na maioria das vezes, o código de modelo é código de biblioteca e a maioria dos programadores são usuários de código de biblioteca, não criadores de código de biblioteca. Isso significa que esse tipo de erro enigmático é realmente difícil de entender quando você não entende como a biblioteca é escrita (não apenas o design, como é realmente implementada). O segundo problema é que, mesmo quando o programador escreveu o código do modelo, os motivos da falha ainda podem ser obscuros porque o compilador poderá dizer que há um problema tarde demais: quando o código gerado está sendo compilado. Se o problema for relativo às propriedades do tipo , verifique-o antes mesmo de gerar o código.
É para isso que os Conceitos permitem (e são projetados): permitir que o programador (código genérico) especifique as propriedades dos tipos que são passados como parâmetros do modelo e, em seguida, permita que o compilador forneça erros explícitos, caso os tipos fornecidos não atendam às requisitos.
Quando a verificação for bem-sucedida, o código será gerado a partir do modelo e então compilado, certamente com sucesso.
Toda a verificação do conceito ocorre exclusivamente antes do tempo de compilação . Ele verifica os próprios tipos, não os tipos de objeto . Não há objeto antes do tempo de compilação.
Agora, sobre "interfaces".
Ao criar um tipo base abstrato ou virtual, você permite que o código o utilize para manipular objetos dos tipos filhos sem conhecer suas implementações reais. Para impor isso, o tipo base expõe membros que são virtuais e podem ser (ou precisam ser) sobrecarregados pelos tipos filhos.
Isso significa que o compilador pode verificar em tempo de compilação que todos os objetos passados para uma função que requer uma referência à classe base devem ser 1. de um dos tipos filhos da classe base, 2. esse tipo filho deve ter implementações de funções puras virtuais declaradas nas classes base, se houver.
Portanto, no tempo de compilação , o compilador verifica as interfaces dos tipos de objeto e informa se algo está faltando.
É a mesma ideia que Concepts, mas ocorre tarde demais , como foi dito na descrição do Concept. Ocorre no tempo de compilação. Não estamos no código genérico (código do modelo), estamos depois que ele foi processado e já é tarde demais para verificar se os tipos atendem aos requisitos genéricos, que não podem ser expostos pelas classes base virtuais. De fato, toda a implementação do paradigma de orientação a objetos em C ++ nem existe quando o código do modelo está sendo processado. Ainda não há objetos. Isso é
As classes descrevem restrições nos objetos a serem usados para verificar os requisitos de funções que manipulam esses objetos. Os conceitos descrevem restrições nos tipos (incluindo classes) a serem usadas para verificar os requisitos de código genérico para gerar código real a partir desses tipos e combinação de código genérico.
Então, novamente, é o mesmo "teste de sanidade", mas em outra camada da linguagem, ou seja, modelos. Os modelos são uma linguagem completa (turing complete) que permite metaprogramação e tipos de programação mesmo antes de aparecerem no código compilado. É um pouco como criar scripts para o compilador. Digamos que você possa criar um script, classes são apenas valores manipulados pelo script. Atualmente, não há como verificar restrições nesses valores além de travar o script de uma maneira não óbvia. Os conceitos são apenas isso: forneça a digitação nesses valores (que no código gerado são tipos). Não tenho certeza se estou claro ...
Outra diferença realmente importante entre as classes base virtuais e os Conceitos é que a primeira força uma forte relação entre os tipos, tornando-os "ligados pelo sangue". Enquanto a metaprogramação de modelos permite "digitação de pato", os Conceitos apenas permitem tornar os requisitos mais claros.