Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

auto variable declaration without definition

Tags:

c++

auto

I was wondering if there's an elegant solution for the following issue:

Let's say I'd like to have a variable holding a value with a pretty complex type and would the compiler to automatically infer it's type, but declare first and give value later in the code because of initialization in an if statement.

For example:

{
  auto a;
  if (some predicate)
      a = init_a(1);
  else
      a = init_a(2);
}

Obviously this code doesn't compile, but the I think that the compiler has all the information it needs to infer the type.

If 'a' was just an int, this was not a problem, but if the type is a complex template, I don't want to have to write it (or in some cases even know it). Also, i wouldn't want to call the default constructor of a and then write over it.

Possible solutions:

  1. Template the type of 'a'.
  2. initialize 'a' using a lambda and move the predicate into the lambda.
  3. Just write the type of 'a' instead auto.
  4. Use a void pointer/shared_ptr and then init 'a' on the heap.

Each of these has its own drawbacks.

Is there a more elegant solution for it?

like image 616
user1912594 Avatar asked Oct 20 '20 12:10

user1912594


People also ask

How do you declare an auto variable?

To use the auto keyword, use it instead of a type to declare a variable, and specify an initialization expression. In addition, you can modify the auto keyword by using specifiers and declarators such as const , volatile , pointer ( * ), reference ( & ), and rvalue reference ( && ).

Can we declare a variable without datatype?

variable a has been declared without any data type and still this program compiles successfully and gives the desired output. see it on ideone. but, when i declared the same variable inside main, it gives compilation error. see here.

What is the difference between variable declaration and definition?

Declaration means that variable is only declared and memory is allocated, but no value is set. However, definition means the variables has been initialized. The same works for variables, arrays, collections, etc.

What is difference between definition and declaration in C++?

Definition associates the variable with a type and allocates memory, whereas declaration just specifies the type but doesn't allocate memory. Declaration is more useful when you want to refer the variable before definition.


Video Answer


3 Answers

The compiler doesn't have infinite lookahead what is happening further on in the code. It only knows what's happening at the current statement. Therefore it can't deduce any types without an initializer.

If you don't know the return-type of init_a then you could use decltype:

decltype(init_a(1)) a;

You can also use a lambda call to initialize the variable:

auto a = [ /* Captures needed for the condition... */ ]()
{
    if (some_condition)
        return init_a(1);
    else
        return init_a(2);
}();  // Call the lambda immediately

Or, as mentioned in many comments, use the ternary conditional expression:

auto a = some_condition ? init_a(1) : init_a(2);
like image 163
Some programmer dude Avatar answered Oct 24 '22 07:10

Some programmer dude


There's a technique called "Immediately Invoked Lambda Expression" that is using lambda to initialize a variable in a complex way. Using this approach your a can be const which improves const-correctness. More details here.

like image 32
Quarra Avatar answered Oct 24 '22 06:10

Quarra


For a simple binary predicate, consider just using the ternary operator:

struct A { int a; };

A initA(int a) { return A{a}; }
bool somePredicate(int input) { return input == 42; }

int main() {
    const auto input = 42;
    const auto a = somePredicate(input) ? initA(1) : initA(2);
}

for more complex initialization logic (beyond a binary case), wrap the initialization logic in a lambda:

struct A { int a; };

A initA(int a) { return A{a}; }
bool somePredicate(int input) { return input == 42; }

int main() {
    const auto input = 42;
    const auto a = []() { 
        if (somePredicate(input)) { return initA(1); }
        else if (input == 100) { return initA(100); }
        else { return initA(2); }}();
}

Both these approaches come with additional possibility of making the variable to be initialized const.

like image 2
dfrib Avatar answered Oct 24 '22 06:10

dfrib