Pergunta

Eu sou um pouco curioso sobre alguns dos novos recursos do C ++ 0x. Em particular gama baseado em loops e < strong> initializer listas . Ambas as funções exigem uma classe definida pelo usuário, a fim de funcionar corretamente.

Eu deparei este post , e enquanto o top-resposta foi útil. Eu não sei se é inteiramente correcto (provavelmente estou apenas completamente mal-entendido, consulte 3ª comentário sobre primeira resposta) . De acordo com as especificações atuais para initializer listas, o cabeçalho define um tipo:

template<class E> class initializer_list {
public:
    initializer_list();

    size_t size() const; // number of elements
    const E* begin() const; // first element
    const E* end() const; // one past the last element
};

Você pode ver isso no caderno de encargos, apenas Ctrl + F 'classe initializer_list' .

Para = {1,2,3} a ser escalado de forma implícita na classe initializer_list, o compilador tem que ter algum conhecimento sobre a relação entre {} e initializer_list. Não há construtor que recebe nada, então o initializer_list tanto quanto eu posso dizer é um invólucro que fica obrigado a tudo o que o compilador está realmente gerando.

É o mesmo com o loop for( : ), que também requer um tipo definido pelo usuário para o trabalho (embora de acordo com as especificações, atualizado para não exigir qualquer código para arrays e initializer listas. Mas initializer listas exigem <initializer_list>, por isso é um usuário exigência do código -definida por procuração).

Am I mal entendido completamente como isso funciona aqui? Eu não estou errado em pensar que esses novos recursos fazem de facto confiar muito fortemente no código do usuário. É como se os recursos são meia-boca, e em vez de construir o recurso inteiro para o compilador, está sendo meia feito pelo compilador e metade feito no inclui. Qual é a razão para isso?

Editar: eu digitei 'dependem fortemente de código de compilador', e não 'dependem fortemente de código do usuário'. O que eu acho completamente jogou fora a minha pergunta. Minha confusão não é sobre os novos recursos que está sendo construído no compilador, é coisas que são construídos no compilador que dependem de código do usuário.

Foi útil?

Solução

Eu não estou errado em pensar que esses novos recursos fazem de facto confiar muito fortemente de código de compilador

Eles confiam muito no compilador. Se você precisa incluir um cabeçalho ou não, o fato é que em ambos os casos, a sintaxe seria um erro de análise com compiladores hoje. O for (:) não se encaixa no padrão de hoje, em que a construção só é permitido é for(;;)

É como se os recursos são meia-boca, e em vez de construir o recurso inteiro para o compilador, está sendo meia feito pelo compilador e metade feito no inclui. Qual é a razão para isso?

O suporte deve ser implementado no compilador, mas você é obrigado a incluir cabeçalho de um sistema para que ele funcione. Isso pode servir a dois propósitos, no caso de listas de inicialização, que traz o tipo (interface para o suporte do compilador) em escopo para o usuário para que você possa ter uma maneira de usá-lo (pensar como va_args estão em C). No caso da gama-baseado em (que é apenas açúcar sintático) você precisa trazer Gama para o escopo para que o compilador pode executar de magia. Note-se que o padrão define for ( for-range-declaration : expression ) statement como equivalente a ([6.5.4] / 1 no desenho):

{ 
   auto && __range = ( expression ); 
   for ( auto __begin = std::Range<_RangeT>::begin(__range), 
         __end = std::Range<_RangeT>::end(__range); 
         __begin != __end; 
         ++__begin ) { 
      for-range-declaration = *__begin; 
      statement 
   } 
} 

Se você quiser usá-lo apenas em matrizes e recipientes STL que poderiam ser implementadas sem o conceito Range (não no sentido C ++ 0x), mas se você deseja estender a sintaxe em classes definidas pelo usuário (seus próprios contentores ) o compilador pode facilmente dependem do modelo Range existente (com a sua própria especialização possível). O mecanismo de dependendo de um molde a ser definido equivale à exigência de uma interface estática no recipiente.

A maioria das outras línguas têm ido no sentido de exigir uma interface comum (dizer Container, ...) e usando o polimorfismo em tempo de execução sobre isso. Se isso era para ser feito em C ++, toda a STL teria que passar por uma grande refatoração como recipientes STL não compartilham uma base comum ou interface, e eles não estão preparados para ser usado polimorphically.

Se houver, o padrão atual não será underbaked no momento em que ele sai.

Outras dicas

É açúcar sintaxe apenas. O compilador irá expandir as dadas construções sintáticas em expressões equivalentes em C ++ que fazem referência os tipos / nomes de símbolo padrão diretamente.

Este não é o único forte acoplamento que compiladores moderno C ++ tem entre sua língua e o "mundo exterior". Por exemplo, extern "C" é um pouco de uma língua cortar para acomodar modelo de vinculação do C. maneiras orientados para a linguagem de declarar o armazenamento local de segmento depende implicitamente muitas RTL hackery ao trabalho.

Ou olhada C. Como você acessar argumentos passados ??via ...? Você precisa contar com a biblioteca padrão; mas que usa a magia que tem uma dependência muito duro sobre como exatamente o compilador C expõe quadros de pilha.

UPDATE:

Se qualquer coisa, a abordagem C ++ tomou aqui é mais no espírito do C ++ do que a alternativa - o que seria para adicionar um intrínseca coleção ou intervalo tipo, cozido na linguagem. Em vez disso, ele está sendo feito através de um tipo de intervalo definido pelo fornecedor. Eu realmente não vejo isso como muito diferente de argumentos variádicos, que são igualmente inútil sem o definido pelo fornecedor acessor macros.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top