Можете ли вы использовать ключевое слово explicit, чтобы предотвратить автоматическое преобразование параметров метода?

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

Вопрос

Я знаю, что вы можете использовать ключевое слово C ++ 'explicit' для конструкторов классов, чтобы предотвратить автоматическое преобразование типа.Можете ли вы использовать эту же команду, чтобы предотвратить преобразование параметров для метода класса?

У меня есть два члена класса, один из которых принимает bool в качестве параметра, другой - unsigned int .Когда я вызвал функцию с помощью int , компилятор преобразовал параметр в bool и вызвал неправильный метод.Я знаю, что в конце концов я заменю bool, но пока не хочу нарушать работу других подпрограмм по мере разработки этой новой подпрограммы.

Это было полезно?

Решение

Нет, вы не можете использовать явное, но вы можете сделать это вместо этого:

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

Повторите этот шаблон для каждого метода, который принимает bool или unsigned int. Не предоставляйте реализацию для шаблонной версии метода.

Это заставит пользователя всегда явно вызывать версию bool или unsigned int.

Любая попытка вызвать Method с типом, отличным от <=> или <=>, не удастся скомпилировать, так как член является частным, разумеется, с учетом стандартных исключений из правил видимости (друг, внутренние вызовы и т. д.). .). Если что-то, имеющее доступ, вызывает закрытый метод, вы получите ошибку компоновщика.

Другие советы

Нет. explicit предотвращает автоматическое преобразование между определенными классами, независимо от контекста.И, конечно, вы не можете сделать это для встроенных классов.

Следующее является очень простой оболочкой, которая может быть использована для создания сильного определения типа:

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
}

Одной из приятных особенностей этого подхода является то, что вы также можете различать разные параметры одного типа. Например, у вас может быть следующее:

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

void foo (Width width, Height height);

Клиентам 'foo' будет понятно, какой аргумент есть какой.

Вам может пригодиться использование шаблонов. Ниже показано, что функция шаблона foo<>() специализируется на bool, unsigned int и int. Функция main() показывает, как разрешаются вызовы. Обратите внимание, что вызовы, использующие константу foo<int>(), в которой не указан суффикс типа, преобразуются в foo( 1), поэтому вы получите сообщение об ошибке "U", если не будете специализироваться на <=>. В этом случае вызывающие абоненты, использующие литеральную целочисленную константу, должны будут использовать суффикс <=>, чтобы получить вызов для разрешения (это может быть желаемое поведение).

В противном случае вам придется специализироваться на <=> и использовать суффикс <=> или привести его к <=> перед передачей его в версию <=> (или, возможно, сделать утверждение, что значение isn ' отрицательно, если это то, что вы хотите).

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

Компилятор дал " неоднозначный вызов " предупреждение, которого будет достаточно.

Я занимался разработкой TDD и не понял, что забыл реализовать соответствующий вызов в фиктивном объекте.

bool - это int, которое ограничено либо 0, либо 1. В этом и заключается вся концепция return 0; логически это то же самое, что сказать return false; (хотя не используйте это в коде).

Вы также можете написать версию int, которая вызывает bool.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top