Обеспечение безопасности типов в C++ без использования дополнительных классов

Я немного знаком с безопасностью типов и успешно использовал ее раньше в методах, которые получают несколько параметров одного и того же типа (bool), чтобы избежать путаницы. Например:

// Old version of the method
void sendPackage(bool sendImmediately, bool dividePacket);

// Type safe version
enum SendImmediatelyPreference
{
    SEND_IMMEDIATELY,
    DO_NOT_SEND_IMMEDIATELY
};

enum PacketDivisionPreference
{
    DIVIDE_PACKET,
    DO_NOT_DIVIDE_PACKET
};

void sendPackage(
    SendImmediateltPreference immediatePref,
    PacketDivisionPreference divisionPref);

Таким образом, загадочное sendPackage(true, false) становится sendPackage(SEND_IMMEDIATELY, DO_NOT_DIVIDE_PACKET).

Проблема в том, что это вариант только для bool. У меня есть метод, который принимает несколько std::vector<std::string>, и я хотел бы свести к минимуму возможность ввода пользователем аргументов в неправильном порядке.

Я могу подумать о создании разных классов, которые содержат std::vector<std::string> и либо переопределяют тонны методов std::vector, либо раскрывают внутренний вектор.

Есть ли более простой способ, какой-то typedef, обеспечивающий безопасность типов? Использование boost было бы в порядке.


person user2891462    schedule 29.03.2017    source источник
comment
См. Boost strong typedef boost.org/doc/libs/ 1_63_0/libs/сериализация/doc/   -  person Richard Critten    schedule 29.03.2017
comment
Я бы рассмотрел этот вопрос. К сожалению, в C++ нет строго типизированных определений типов, но вы можете попытаться обойти это.   -  person Bartek Banachewicz    schedule 29.03.2017
comment
Я не знаю, как обеспечить безопасность типов без использования разных типов. Я полагаю, вы могли бы использовать std::pair так: struct type1{}; struct type2{}; std::pair<type1, std::vector<std::string>> v1; std::pair<type2, std::vector<std::string>> v2;   -  person Galik    schedule 29.03.2017
comment
Спасибо за ваши ответы, @BartekBanachewicz и @RichardCritten. BOOST_STRONG_TYPEDEF кажется тем, что я ищу, но полезно знать о его ограничениях :)   -  person user2891462    schedule 29.03.2017


Ответы (5)


Как насчет альтернативного подхода с использованием именованных параметров? Существует несколько способов сделать это в C++, описанных здесь. Теговый подход с использованием кортежа выглядит разумным. Существует также параметр повышения.

Это не обеспечивает строгую безопасность типов, но вы можете возразить, что пользователь с такой же вероятностью вызовет неправильный конструктор, чтобы сделать свой тип безопасным объектом, как и использует неправильный тег при вызове вашей функции. Эта ситуация менее вероятна, если типы используются во всем приложении, а не определены только для одной конкретной функции.

См. также обсуждение параметра boost strong typedef vs для аналогичной цели здесь.

person Mitchell Kline    schedule 29.03.2017

Не уверен, что правильно вас понял, но, возможно, это может помочь:

enum SendImmediatelyPreference : bool  // allows only 2 options:
{
  DO_NOT_SEND_IMMEDIATELY,  // false
  SEND_IMMEDIATELY          // true
}
person Alexandr Derkach    schedule 29.03.2017
comment
Нет, извините, это не отвечает на мой вопрос (который связан с векторами, хотя в идеале это был бы общий ответ) - person user2891462; 29.03.2017

Как насчет создания класса, который наследует (общедоступный) от std::vector, чтобы иметь сильную проверку типов. Преимущество в том, что вам нужно только переписать конструкторы.

Вы также можете перегруппировать свои параметры в std::unordered_map>, чтобы реализовать аргумент как dict (например, в python или javascript).

person eti_nne    schedule 29.03.2017
comment
Я думал об этой возможности, но мне не нравится расширять STL (хотя, возможно, мне следует быть более гибким). - person user2891462; 29.03.2017

BOOST_STRONG_TYPEDEF — это именно typedef, который обеспечивает тип безопасность.

Однако этот ответ содержит некоторые предостережения, связанные с использованием этого сильного typedef только для функции, и утверждает, что типы следует использовать по всему коду, чтобы предотвратить ненужные приведения.

person user2891462    schedule 29.03.2017

Мне нравится объединять параметры в класс конфигурации или структуру. Например:

struct SendOptions
{
    bool send_immediately = false;
    bool divide_packet = false;
    // ...
};

void sendPackage(SendOptions options);

Это имеет дополнительное преимущество, поскольку дополнительные параметры могут быть добавлены позже без необходимости изменения интерфейса sendPackage(SendOptions).

Это не повышает безопасность типов, но помогает предотвратить ошибки (особенно при большом количестве параметров), что, вероятно, является целью, которую вы пытаетесь достичь.

person StackedCrooked    schedule 10.05.2018