Reputation: 75
Is there a way to check if certain variable is initialized before some point in a program?
For example, how to check if certain variable is initialized somewhere before the IfStmt
node?
Methods from VarDecl
class (hasInit()
and getInit()
) are not enough because of the following situation:
int x = 0; // hasInit() return true
int y;
...
y = 0; // initialized here, but hasInit() returns false
...
if (...) {}
Upvotes: 2
Views: 175
Reputation: 3276
Firstly as mentioned in the comments:
int y = 0; // initialization
int y; y = 0; // assignment
Let's assume you want to detect assignment. One simple way could be wrap the integer you want to track in a struct and write a custom operator = (int)
. For example:
struct Foo
{
Foo() {std::cout << "default init" << std::endl;}
Foo& operator = (int elem)
{
cout<<"Int-Assignment operator called "<<endl;
x = elem;
is_assigned = true;
return *this;
}
int x = 0; // default initialized to 0
bool is_assigned = false; // default initialized to false
};
Now let's see what happens:
int main()
{
Foo t1;
// t1.is_assigned is false
t1 = 0;
// t1.is_assigned is true
return 0;
}
You could use something like this or a variant if needed. Here's the code running online corresponding to the above.
Is this what you wanted?
Upvotes: 1
Reputation: 2880
If you maintain a product written by C++ code and hope to remove ugly indeterminate variables, a reasonable way to do it is defining an initializing function or lambda f
, and then declare a local variable as const auto x = f(...);
from the get-go.
OTOH, if you delay the value asignment on purpose, there are several methods to detect the value is assigned or not. I just came up with following methods.
std::optional
In C++17 and over,
std::optional<T>
enables us to detect whether values are assigned or not.
std::optional::has_value
and std::optional::value
correspond to your hasInit
and getInit
respectively as follows:
#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 output is as follows:
Value is still not assigned.
Value is assigned by 1.
std::unique_ptr
We can also check it using std::unique_ptr<T>
which is introduced from C++11.
First we define a variable as std::unique_ptr<T> x;
where (x == nullptr)
is still true.
Later on, we assign a value by x = std::unique_ptr<int>(new int(1))
and then (x == nullptr)
becomes false.
(In C++14 x = std::make_unique<int>(1)
works and is simple.)
Thus we can again get the previous output with the following code:
#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
We can also apply std::pair<bool, T>
where std::pair::first
and std::pair::second
correspond to your hasInit
and getInit
respectively.
We again get the previous output:
#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;
}
Upvotes: 1