Pergunta

tipo de pergunta aleatória ...

O que eu estou procurando é uma maneira de expressar uma operação de conversão que usa um operador definido da instância de classe Eu estou lançando a partir de, e gera um erro de tempo de compilação se não há um operador de conversão definido para o tipo . Assim, por exemplo, o que eu estou procurando é algo como:

template< typename RESULT_TYPE, typename INPUT_TYPE >
RESULT_TYPE operator_cast( const INPUT_TYPE& tValue )
{
    return tValue.operator RESULT_TYPE();
}

// Should work...
CString sString;
LPCTSTR pcszString = operator_cast< LPCTSTR >( sString );

// Should fail...
int iValue = 42;
DWORD dwValue = operator_cast< DWORD >( iValue );

Interessante nota lateral:. O código acima trava o compilador VS2005 C ++, e não compila corretamente no compilador VS2008 C ++ devido ao que eu estou supondo que é um erro do compilador, mas espero que demonstra a idéia

Alguém sabe de alguma maneira de conseguir esse efeito?

Edit: mais lógica, para explicar por que você pode usar este. Digamos que você tenha uma classe de invólucro que é suposto para encapsular ou tipo de um abstrato, e você está lançando-a por tipo encapsulado. Você poderia usar static_cast <>, mas que o trabalho poder quando se queria a falhar (ou seja: o compilador escolhe um operador que tem permissão para converter para o tipo que você pediu, quando você queria um fracasso, porque esse operador não está presente).

É certo que é um caso raro, mas é irritante que eu não posso expressar exatamente o que eu quero que o compilador para fazer em uma função encapsulado ... daí a pergunta aqui.

Foi útil?

Solução

O código que você postou trabalhos com a Cameau compilador (que normalmente é uma indicação boa que é válido C ++).

Como você sabe um elenco válido consiste em não mais de um usuário definiu elenco, assim que uma possível solução que eu estava pensando estava adicionando outro usuário elenco definido através da definição de um novo tipo no modelo elenco e ter um estática assert que nenhum elenco é disponível a partir do novo tipo para o tipo de resultado (usando impulsionar is_convertible ), porém este não distingue entre operadores elenco e construtores elenco (ctor com um argumento) e alows moldes adicionais a ter lugar (por exemplo void* para bool). Eu não tenho certeza se fazer uma distinção entre operadores elenco e construtores elenco é o da correta coisa a fazer, mas isso é o que a pergunta estados.

Depois de um par de dias ponderando sobre isso, ele me bateu, você pode simplesmente tomar o endereço do operador de conversão. Isto é um pouco mais fácil dizer do que fazer devido ao ponteiro peludo C ++ 's à sintaxe membro (que me levou caminho mais longo do que o esperado para obtê-lo à direita). Eu não sei se isso funciona no VS2008, eu só verifiquei em Cameau.

template< typename Res, typename T>
Res operator_cast( const T& t )
{
    typedef Res (T::*cast_op_t)() const;
    cast_op_t cast_op = &T::operator Res;
    return (t.*cast_op)();
}

Editar: Eu tive a chance de testá-lo em VS2005 e VS2008. Meus resultados diferem do cartaz original de.

  • No VS2008 a versão original parece funcionar bem (como faz o meu).
  • No VS2005 a versão original só trava o compilador quando casting de um construído em tipo (por exemplo elenco int para int) depois de fornecer um erro de compilação que não parece tão ruim também eu e minha versão parece obras em todos os casos.

Outras dicas

Usando um construtor de conversão marcada explícita é como você impediria o compilador de permitir tipos implicitamente convertidos de inicializar sua classe wrapper.

Como mensagens de erro compilador modelo relacionadas são geralmente uma dor completa para desvendar, se você não se importa especificando cada conversão você pode obter o compilador para emitir uma mensagem mais instrutivo no caso falhar, fornecendo uma definição de modelo padrão também. Isto usa o fato de que o compilador só irá tentar compilar o código em modelos que na verdade é invocado.

#include <string>

// Class to trigger compiler warning   
class NO_OPERATOR_CONVERSION_AVAILABLE
{
private:
   NO_OPERATOR_CONVERSION_AVAILABLE(){};
};

// Default template definition to cause compiler error
template<typename T1, typename T2> T1 operator_cast(const T2&)
{
   NO_OPERATOR_CONVERSION_AVAILABLE a;
   return T1();
}

// Template specialisation
template<> std::string operator_cast(const std::string &x)
{
   return x;
}

Parece que você quer especialização de modelo, algo como isto faria:

/* general template */
template<typename T1, typename T2> T1 operator_cast(const T2 &x);

/* do this for each valid cast */
template<> LPCTSTR operator_cast(const CString &x) { return (LPCTSTR)x; }

EDIT:. Como observado em outro post, você pode colocar algo na versão geral para dar-lhe uma mensagem de erro mais útil se um elenco sem suporte é realizado

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