Jan Halsema
Jan Halsema

Reputation: 31

variable declaration in function return type specifier c++type

I was trying out codefights.com and noticed someones answer to a question which involved giving all the longest strings in a vector do this:

std::vector<std::string> r, allLongestStrings(std::vector<std::string> a) {
    int b=0;
    for (s:a) if (s.size()>b) b=s.size();
    for (s:a) if (s.size()==b) r.push_back(s);
    return r;
}

He's declaring a variable in the return type specifier for the function, can anyone tell me why this is allowed? I't doesn't compile on my machine and I couldn't find a gcc extension that does this, thanks in advance :).

Upvotes: 2

Views: 828

Answers (2)

user7860670
user7860670

Reputation: 37599

The mixed variable / function declaration seems to be ok, though gcc complains that function definition shouldn't be there but I think it's ok at global scope. But it's a 100% valid syntax even in non-global scope if no function definition is given. This declaration is just regular declarations of several items of the same leading type. For example we can declare multiple items of different kinds but with same leading like this:

// single line declaration
int i = 0, * p_i = nullptr, ai[2] = {42,42}, geti(void), * * getppi(void);
// the same as
int i = 0;
int * p_i = nullptr;
int ai[2] = {42, 42};
int geti(void);
int ** getppi(void);

So r is just a regular variable of type std::vector<std::string>, followed by function allLongestStrings that returns the same std::vector type.

This compact declaration form exists for historical reasons. Basically it helped to save quite some bytes for storing and compiling the source file.

This form of for loop is probably on of the earlier experimental extensions before current form was standardized.

Upvotes: 0

zett42
zett42

Reputation: 27776

Looking at the reference (decl-specifier-seq), I don't see how it would be possible to declare the return variable before the function name.

With C++14, you can use the auto keyword to remove the duplicate mentioning of the return type:

auto allLongestStrings( const std::vector<std::string>& a ) {
    std::vector<std::string> r;
    std::size_t b = 0;
    for( const auto& s : a ) if( s.size() > b ) b = s.size();
    for( const auto& s : a ) if( s.size() == b ) r.push_back( s );
    return r;
}

I fixed some other things of the code:

  • to improve efficiency, declare the parameter a as const reference, so it won't be copied
  • declare b as std::size_t to match return type of std::vector::size()
  • in range-for loop, a type specifier is necessary (even if it is auto); added const reference for efficiency

Live demo.

Upvotes: 1

Related Questions