¿Se puede utilizar una palabra clave explícita para evitar la conversión automática de los parámetros del método?

StackOverflow https://stackoverflow.com/questions/175689

Pregunta

Sé que puedes usar la palabra clave C++ 'explícita' para que los constructores de clases eviten una conversión automática de tipo.¿Puedes usar este mismo comando para evitar la conversión de parámetros para un método de clase?

Tengo dos miembros de clase, uno que toma un bool como parámetro y el otro un int sin signo.Cuando llamé a la función con un int, el compilador convirtió el parámetro en bool y llamó al método incorrecto.Sé que eventualmente reemplazaré el bool, pero por ahora no quiero interrumpir las otras rutinas a medida que se desarrolla esta nueva rutina.

¿Fue útil?

Solución

No, no puede usar explícito, pero puede hacer esto en su lugar:

class ClassThatOnlyTakesBoolsAndUIntsAsArguments
{
public:
  void Method(bool arg1);
  void Method(unsigned int arg1);

  // Below just an example showing how to do the same thing with more arguments
  void MethodWithMoreParms(bool arg1, SomeType& arg2);
  void MethodWithMoreParms(unsigned int arg1, SomeType& arg2);

private:
  template<typename T>
  void Method(T arg1);

  // Below just an example showing how to do the same thing with more arguments
  template<typename T>
  void MethodWithMoreParms(T arg1, SomeType& arg2);
};

Repita este patrón para cada método que tome el bool o unsigned int. No proporcione una implementación para la versión con plantilla del método.

Esto obligará al usuario a llamar siempre explícitamente a la versión bool o unsigned int.

Cualquier intento de llamar a Method con un tipo que no sea <=> o <=> no se compilará porque el miembro es privado, sujeto a las excepciones estándar a las reglas de visibilidad, por supuesto (amigo, llamadas internas, etc. .). Si algo que tiene acceso llama al método privado, obtendrá un error de vinculador.

Otros consejos

No. explicit evita la conversión automática entre clases específicas, independientemente del contexto. Y, por supuesto, no puede hacerlo para las clases integradas.

El siguiente es un contenedor muy básico que se puede utilizar para crear una definición de tipo fuerte:

template <typename V, class D> 
class StrongType
{
public:
  inline explicit StrongType(V const &v)
  : m_v(v)
  {}

  inline operator V () const
  {
    return m_v;
  }

private:
  V m_v; // use V as "inner" type
};

class Tag1;
typedef StrongType<int, Tag1> Tag1Type;


void b1 (Tag1Type);

void b2 (int i)
{
  b1 (Tag1Type (i));
  b1 (i);                // Error
}

Una buena característica de este enfoque es que también puede distinguir entre diferentes parámetros con el mismo tipo. Por ejemplo, podría tener lo siguiente:

class WidthTag;
typedef StrongType<int, WidthTag> Width;  
class HeightTag;
typedef StrongType<int, HeightTag> Height;  

void foo (Width width, Height height);

Será claro para los clientes de 'foo' qué argumento es cuál.

Algo que podría funcionar para ti es utilizar plantillas.A continuación se muestra la función de plantilla. foo<>() estar especializado para bool, unsigned int, y int.El main() La función muestra cómo se resuelven las llamadas.Tenga en cuenta que las llamadas que utilizan una constante int que no especifican un sufijo de tipo se resolverán como foo<int>(), entonces obtendrás un error al llamar foo( 1) si no te especializas en int.Si este es el caso, las personas que llaman usando una constante entera literal tendrán que usar el "U" sufijo para que la llamada se resuelva (este podría ser el comportamiento que desea).

De lo contrario tendrás que especializarte en int y usar el "U" sufijo o convertirlo en un unsigned int antes de pasarlo al unsigned int versión (o tal vez afirmar que el valor no es negativo, si eso es lo que desea).

#include <stdio.h>

template <typename T>
void foo( T);

template <>
void foo<bool>( bool x)
{
    printf( "foo( bool)\n");
}


template <>
void foo<unsigned int>( unsigned int x)
{
    printf( "foo( unsigned int)\n");
}


template <>
void foo<int>( int x)
{
    printf( "foo( int)\n");
}



int main () 
{
    foo( true);
    foo( false);
    foo( static_cast<unsigned int>( 0));
    foo( 0U);
    foo( 1U);
    foo( 2U);
    foo( 0);
    foo( 1);
    foo( 2);
}

El compilador dio " llamada ambigua " advertencia, que será suficiente.

Estaba desarrollando TDD y no me di cuenta de que olvidé implementar la llamada correspondiente en el objeto simulado.

bool ES un int que está limitado a 0 o 1. Ese es todo el concepto de return 0 ;, es lógicamente lo mismo que decir return false; (sin embargo, no use esto en el código).

También podría escribir una versión int que llame a la versión bool.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top