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?

4 Answers 4

34

In C99 this works:

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

..and similar things can be done with structs.

Sign up to request clarification or add additional context in comments.

3 Comments

Sadly doesn't work in C++. You get the error "taking address of temporary array".
Works with clang 6.0 (cpp)
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?
10

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.

1 Comment

Actually, this will work with any container class, thanks to C++11's uniform initialization.
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.

Comments

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);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.