array's initialization body as function parameter (C-array), is it possible?
Asked Answered
H

4

25

I am searching for some help in next situation:
I have some class and some method in it, syntax is like this:

class SomeClass {  
    public:  
            void doSomething(int *a);  
};

So I want to call this method like

SomeClass::doSomething({ 0, 1, 2, 3, 4 });

Is it possible in any language? Any (C++, C, obj-c, obj-c++) implementation is welcome! I know that this initialization block is a body of array, like

int *a = { 0, 1, 2, 3, 4 };
SomeClass::doSomething(a);

But interface will look great, I think, if there will be no temp variables before function calls (as we don't need to know the type of parameter in class-client). So, is there any chance to make this?

Hydrocellulose answered 5/10, 2011 at 7:17 Comment(0)
C
9

This is about C++11 initializer lists (section 18.9).

void foo (std :: initializer_list <int> inputs) {
    for (auto i : inputs) {
        // ...
    }
}

foo ({10, 20, 30});

Only the compiler can create an initializer list, but you can treat it like a standard STL-style container with begin(), end(), size(), and random-access iterators.

std::vector (and I expect some other containers) can now be constructed with initializer lists, so

std :: vector <std :: string> foo {"a", "b"};

is equivalent to

std :: vector <std :: string> foo;
foo .push_back ("a");
foo .push_back ("b");

except that it may perform fewer allocations. Note that the const char* have been turned into std::string automagically.

Choreography answered 5/10, 2011 at 7:19 Comment(1)
Actually, this will work with any container class, thanks to C++11's uniform initialization.Intimist
L
34

In C99 this works:

functionThatTakesIntPtrOrArray( (int []){ 1, 2, 3, 4 } );

..and similar things can be done with structs.

Levitt answered 5/10, 2011 at 7:33 Comment(3)
Sadly doesn't work in C++. You get the error "taking address of temporary array".Ricci
Works with clang 6.0 (cpp)Verruca
I have been using this technique in Xcode with clang, and recently tried to compile it in visual studio 2017 without any success. I was wondering if this has any name, and why VS does not support it?Lelahleland
C
9

This is about C++11 initializer lists (section 18.9).

void foo (std :: initializer_list <int> inputs) {
    for (auto i : inputs) {
        // ...
    }
}

foo ({10, 20, 30});

Only the compiler can create an initializer list, but you can treat it like a standard STL-style container with begin(), end(), size(), and random-access iterators.

std::vector (and I expect some other containers) can now be constructed with initializer lists, so

std :: vector <std :: string> foo {"a", "b"};

is equivalent to

std :: vector <std :: string> foo;
foo .push_back ("a");
foo .push_back ("b");

except that it may perform fewer allocations. Note that the const char* have been turned into std::string automagically.

Choreography answered 5/10, 2011 at 7:19 Comment(1)
Actually, this will work with any container class, thanks to C++11's uniform initialization.Intimist
S
2

If initializer_list is not available, and the arrays are mostly small, there is another option, overloading << operator for std::vector like this:

template <typename T>
inline std::vector<T> operator <<( const std::vector<T>& vec, const T& val ) {
    std::vector<T> result(vec);
    result.push_back(val);
    return result;
}

With that, you can do this:

void foo (const std::vector<int>& inputs) {
    // ...
}

foo ( std::vector<int>() << 10 << 20 << 30 );

There is a price to pay for this convenience of single line initialization and not having to specify vector size. A copy of the prior vector is created for every element that is added, making running time at least quadratic in vector size -- that's why this is best suited for short vectors and cases when performance does not matter. There is a better solution for C++11, as pointed out in spraff's answer.

Stomatology answered 24/9, 2015 at 23:12 Comment(0)
T
0

one can initialize a temporary array as a function parameter like so

// onboard LED
const byte LED_RED = 36;
const byte LED_BLUE = 34;
const byte LED_GREEN = 35;
    
void turnOffLedAll(){
        // TURN OFF ALL LED
      digitalWrite(LED_RED, LOW);
      digitalWrite(LED_BLUE, LOW);
      digitalWrite(LED_GREEN, LOW);
    }
    
void statusLED(byte led[], byte stat, byte time=0) {
      turnOffLedAll();
      // turn ON LED
      for(int i=0; i<(sizeof(led)/sizeof(led[0])); i++){
        digitalWrite(led[i], stat);
      }
      if (time>0){
        delay(time*1000);
        turnOffLedAll();
      }
    }  
    

Considering the functions above an inline array initialization as a function parameter can be done like this:

   statusLED((byte*)(const byte[]){LED_RED}, LOW, 0);
Todtoday answered 1/1, 2023 at 17:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.