Я знаю, что было несколько хороших решений, но в качестве альтернативы If
ваши значения будут известны во время компиляции, вместо оператора switch вы можете использовать constexpr
с static function template
и парой enumerators
; это будет выглядеть примерно так в одном классе:
#include <iostream>
class ColorInfo {
public:
enum ColorRecipient {
CR_0 = 0,
CR_1,
CR_2
};
enum ColorType {
CT_0 = 123,
CT_1 = 234,
CT_2 = 345
};
template<const uint8_t Iter>
static constexpr uint16_t updateColor() {
if constexpr (Iter == CR_0) {
std::cout << "ColorData updated to: " << CT_0 << '\n';
return CT_0;
}
if constexpr (Iter == CR_1) {
std::cout << "ColorData updated to: " << CT_1 << '\n';
return CT_1;
}
if constexpr (Iter == CR_2) {
std::cout << "ColorData updated to: " << CT_2 << '\n';
return CT_2;
}
}
};
int main() {
const uint16_t colorRecipient0 = ColorInfo::updateColor<ColorInfo::CR_0>();
const uint16_t colorRecipient1 = ColorInfo::updateColor<ColorInfo::CR_1>();
const uint16_t colorRecipient2 = ColorInfo::updateColor<ColorInfo::CR_2>();
std::cout << "\n--------------------------------\n";
std::cout << "Recipient0: " << colorRecipient0 << '\n'
<< "Recipient1: " << colorRecipient1 << '\n'
<< "Recipient2: " << colorRecipient2 << '\n';
return 0;
}
Операторы cout
в if constexpr
добавляются только для целей тестирования, но это должно проиллюстрировать еще один возможный способ сделать это без использования оператора switch, если ваши значения будут известны во время компиляции. Если эти значения генерируются во время выполнения, я не совсем уверен, есть ли способ использовать constexpr
для достижения такого типа структуры кода, но если есть, я был бы признателен, если кто-то еще с немного большим опытом мог бы разработать о том, как это можно сделать с constexpr
, используя runtime
значения. Тем не менее, этот код очень удобочитаем, поскольку в нем нет magic numbers
, а код достаточно выразителен.
- Обновление -
Прочитав больше о constexpr
, я понял, что их можно использовать для генерации compile time constants
. Я также узнал, что они не могут генерировать runtime constants
, но они могут быть использованы в runtime function
. Мы можем взять описанную выше структуру класса и использовать ее в функции времени выполнения как таковой, добавив static function
в класс:
static uint16_t colorUpdater(const uint8_t input) {
// Don't forget to offset input due to std::cin with ASCII value.
if ( (input - '0') == CR_0)
return updateColor<CR_0>();
if ( (input - '0') == CR_1)
return updateColor<CR_1>();
if ( (input - '0') == CR_2)
return updateColor<CR_2>();
return updateColor<CR_2>(); // Return the default type
}
Однако я хочу изменить соглашения об именах двух функций. Первую функцию я назову colorUpdater()
, а эту новую функцию, которую я только что показал выше, я назову updateColor()
, так как она кажется более интуитивно понятной. Таким образом, обновленный класс теперь будет выглядеть так:
class ColorInfo {
public:
enum ColorRecipient {
CR_0 = 0,
CR_1,
CR_2
};
enum ColorType {
CT_0 = 123,
CT_1 = 234,
CT_2 = 345
};
static uint16_t updateColor(uint8_t input) {
if ( (input - '0') == CR_0 ) {
return colorUpdater<CR_0>();
}
if ( (input - '0') == CR_1 ) {
return colorUpdater<CR_1>();
}
if ( (input - '0') == CR_2 ) {
return colorUpdater<CR_2>();
}
return colorUpdater<CR_0>(); // Return the default type
}
template<const uint8_t Iter>
static constexpr uint16_t colorUpdater() {
if constexpr (Iter == CR_0) {
std::cout << "ColorData updated to: " << CT_0 << '\n';
return CT_0;
}
if constexpr (Iter == CR_1) {
std::cout << "ColorData updated to: " << CT_1 << '\n';
return CT_1;
}
if constexpr (Iter == CR_2) {
std::cout << "ColorData updated to: " << CT_2 << '\n';
return CT_2;
}
}
};
Если вы хотите использовать это только с константами времени компиляции, вы можете использовать его так же, как и раньше, но с обновленным именем функции.
#include <iostream>
int main() {
auto output0 = ColorInfo::colorUpdater<ColorInfo::CR_0>();
auto output1 = ColorInfo::colorUpdater<ColorInfo::CR_1>();
auto output2 = ColorInfo::colorUpdater<ColorInfo::CR_2>();
std::cout << "\n--------------------------------\n";
std::cout << "Recipient0: " << output0 << '\n'
<< "Recipient1: " << output1 << '\n'
<< "Recipient2: " << output2 << '\n';
return 0;
}
И если вы хотите использовать этот механизм со значениями runtime
, вы можете просто сделать следующее:
int main() {
uint8_t input;
std::cout << "Please enter input value [0,2]\n";
std::cin >> input;
auto output = ColorInfo::updateColor(input);
std::cout << "Output: " << output << '\n';
return 0;
}
И это будет работать со значениями времени выполнения.