Pouvez-vous utiliser le mot clé explicit pour empêcher la conversion automatique des paramètres de méthode?

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

Question

Je sais que vous pouvez utiliser le mot clé C ++ 'explicitement' pour les constructeurs de classes afin d'empêcher une conversion automatique de type. Pouvez-vous utiliser cette même commande pour empêcher la conversion de paramètres pour une méthode de classe?

J'ai deux membres de la classe, l'un qui prend un bool comme paramètre, l'autre un unsigned int. Quand j'ai appelé la fonction avec un int, le compilateur a converti le paramètre en bool et a appelé la mauvaise méthode. Je sais que je vais éventuellement remplacer le booléen, mais pour le moment, je ne veux pas rompre avec les autres routines pendant que cette nouvelle routine est développée.

Était-ce utile?

La solution

Non, vous ne pouvez pas utiliser explicitement, mais vous pouvez le faire à la place:

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);
};

Répétez ce modèle pour chaque méthode prenant bool ou unsigned int. Ne fournissez pas d'implémentation pour la version gabarit de la méthode.

Ceci forcera l'utilisateur à toujours appeler explicitement la version bool ou unsigned int.

Toute tentative d'appeler Method avec un type autre que <=> ou <=> échouera à la compilation car le membre est privé, sous réserve des exceptions standard aux règles de visibilité, bien entendu (ami, appels internes, etc. .) Si quelque chose ayant accès appelle la méthode privée, vous obtiendrez une erreur de l'éditeur de liens.

Autres conseils

Non. explicit empêche la conversion automatique entre des classes spécifiques, quel que soit le contexte. Et bien sûr, vous ne pouvez pas le faire pour les classes intégrées.

Ce qui suit est un wrapper très basique qui peut être utilisé pour créer un typedef fort:

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
}

Une caractéristique intéressante de cette approche est que vous pouvez également distinguer différents paramètres de même type. Par exemple, vous pourriez avoir ce qui suit:

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

void foo (Width width, Height height);

Les clients de "foo" sauront quel argument est lequel.

Quelque chose qui pourrait fonctionner pour vous est d’utiliser des modèles. Ce qui suit montre que la fonction de modèle foo<>() étant spécialisée pour bool, unsigned int et int. La fonction main() montre comment les appels sont résolus. Notez que les appels qui utilisent une constante foo<int>() qui ne spécifie pas de suffixe de type seront résolus en foo( 1); vous obtiendrez donc une erreur lorsque vous appelez "U" si vous ne vous spécialisez pas sur <=>. Si tel est le cas, les appelants utilisant une constante entière littérale devront utiliser le suffixe <=> pour que l'appel soit résolu (il peut s'agir du comportement souhaité).

Sinon, vous devrez vous spécialiser sur <=> et utiliser le suffixe <=> ou le convertir en <=> avant de le transmettre à la version <=> (ou peut-être faire une affirmation selon laquelle la valeur isn ' t négatif, si c’est ce que vous voulez).

#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);
}

Le compilateur a donné & "; appel ambigu &"; avertissement, qui sera suffisant.

Je faisais du développement TDD et je ne savais pas que j'avais oublié d'implémenter l'appel correspondant dans l'objet fictif.

bool EST un entier limité à 0 ou 1. C’est tout le concept de return 0 ;, c’est logiquement la même chose que de dire return false (ne l’utilisez pas dans le code).

Vous pouvez aussi écrire une version de type int qui appelle la version bool.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top