Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Expected an identifier

Tags:

c++

I was trying to find the absolute sum of an array.

#include <iostream>
#include <vector>
using namespace std;

int getAbsSum(vector<int> arr) {
    int result = 0;
    for (int i = 0; i < arr.size(); i++)
    {
        result += abs(arr[i]);
    }

    return result;
}

int main() {
    cout << getAbsSum([3, 2, -3, -4]);
    return 0;
}

but I got this error that says "Expected an identifier" in my main function. I tried adding a typename before the array, like this

 cout << getAbsSum(int [3, 2, -3, -4]);

but it did not work.

like image 235
AliZe198 Avatar asked Nov 15 '25 19:11

AliZe198


1 Answers

The meaning of [ ] is not what you convey in your example. [ ] is used to indicate array indices, and it only supports one argument. Hence, the expression 3, 2, -3, -4 in this context means evaluate 3, then evaluate 2, then -3, then -4 and return the result of evaluating -4. See

https://en.cppreference.com/w/cpp/language/operator_other

Because the expressions 3, 2 and -3 have no side effects, the result here is the same as if you just wrote -4. With respect to expecting an identifier error, the operator [ ] requires a variable in front of it, so arr[1] means return the second object in array (or container) arr. The solution is to use the correct syntax for list-initialization, which is a form of uniform initialization (do not confuse with aggregate initialization, which is for aggregates. Vectors are not aggregates):

cout << getAbsSum({3, 2, -3, -4});

Also, I recommend not using using namespace std; in the global workspace, but only inside scopes, i.e. in functions, where the effect is limited in scope. A modern version of this function can be rewritten as follows:

#include <iostream>
#include <vector>
#include <chrono>

template <typename E = int,
    template <typename> typename T = std::vector>
E getAbsSum(T<E> const& arr){ 
    E result {};
    for (E element : arr)
    {
        result += abs(element);
    }
    return result;
}

int main() {
    using namespace std;
    using namespace std::literals;
    cout << getAbsSum({3, 2, -3, -4}) << '\n';
    cout << getAbsSum(vector<double>{2.3, 4.5, 6}) << '\n';
    cout << getAbsSum(vector<chrono::seconds>{10s, 1min}).count() << '\n';
    return 0;
}

This version supports any arithmetic type and any container.

In response to @foodiecookies:

(1) Here, the line E result {}; means that the default constructor for E is called. If we used E result = 0 then there would be an error on initialization of chrono::seconds, but if we used E result, the arithmetic types would not get initialized, which is undefined behavior. E result {} calls the default constructor on complex types and a value of 0 or equivalent (0.f, 0., false, ...) for basic types.

(2) for (auto var : container) is a range-based loop. See https://en.cppreference.com/w/cpp/language/range-for It is considered safer and easier to read. Use the old for(;;) when you are not iterating over all the elements in the container.

(bonus) abs(element) finds the correct version of the abs function thanks to Argument Dependent Lookup https://en.cppreference.com/w/cpp/language/adl

like image 176
Arjonais Avatar answered Nov 18 '25 08:11

Arjonais



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!