Если вы поддерживаете продукт, написанный на коде C ++, и надеетесь удалить уродливые неопределенные переменные, разумным способом сделать это будет определение инициализирующей функции или лямбда f
, а затем объявление локальной переменной как const auto x = f(...);
из get-go.
OTOH, если вы задерживаете присвоение значения с целью , существует несколько способов определить, назначено ли значение или нет.Я только что предложил следующие методы:
std :: необязательный
В C ++ 17 и более, std::optional<T>
позволяет нам определять, являются ли значенияназначены или нет.std::optional::has_value
и std::optional::value
соответствуют вашим hasInit
и getInit
соответственно следующим образом:
DEMO
#include <iostream>
#include <optional>
template<typename T>
void checkInitialization(const std::optional<T>& a)
{
if(a.has_value()){
std::cout << "Value is assigned by " << a.value() << "." << std::endl;
}
else{
std::cout << "Value is still not assigned." << std::endl;
}
}
int main(void)
{
std::optional<int> x;
checkInitialization(x); // Value is still not assigned
x = 1;
checkInitialization(x); // Value is assigned
return 0;
}
Theвывод выглядит следующим образом:
Значение по-прежнему не назначено.
Значение присваивается 1.
std ::unique_ptr
Мы также можем проверить это, используя std::unique_ptr<T>
, который представлен в C ++ 11.Сначала мы определяем переменную как std::unique_ptr<T> x;
, где (x == nullptr)
все еще имеет значение true.Позже мы присваиваем значение x = std::unique_ptr<int>(new int(1))
, а затем (x == nullptr)
становится ложным.(В C ++ 14 x = std::make_unique<int>(1)
работает и прост.) Таким образом, мы снова можем получить предыдущий вывод со следующим кодом:
DEMO
#include <iostream>
#include <memory>
template<typename T>
bool hasInit(const std::unique_ptr<T>& a)
{
return (a != nullptr);
}
template<typename T>
const T& getInit(const std::unique_ptr<T>& a)
{
return *a;
}
template<typename T>
void checkInitialization(const std::unique_ptr<T>& a)
{
if(hasInit(a)){
std::cout << "Value is assigned by " << getInit(a) << "." << std::endl;
}
else{
std::cout << "Value is still not assigned." << std::endl;
}
}
int main(void)
{
std::unique_ptr<int> x;
checkInitialization(x); // Uninitialized
x = std::unique_ptr<int>(new int(1));
//x = std::make_unique<int>(1); // C++14
checkInitialization(x); // Initialized
return 0;
}
std :: pair
Мы также можем применить std::pair<bool, T>
, где std::pair::first
и std::pair::second
соответствуют вашим hasInit
и getInit
соответственно.Мы снова получаем предыдущий вывод:
DEMO
#include <iostream>
#include <utility>
template<typename T>
void checkInitialization(const std::pair<bool, T>& a)
{
if(a.first){
std::cout << "Value is assigned by " << a.second << "." << std::endl;
}
else{
std::cout << "Value is still not assigned." << std::endl;
}
}
int main(void)
{
std::pair<bool, int> x{false, 0};
checkInitialization(x); // Uninitialized
x = {true, 1};
checkInitialization(x); // Initialized
return 0;
}