Is Auto as a Parameter in a Regular Function a Gcc 4.9 Extension

auto parameter type in functions

Ok, so thanks to Piotr pointing this other question asking about the same thing, I found the information in a comment that will resolve this, here it is:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4040.pdf

page 16, chapter 5.1.1 named generic functions

A generic function is a function template whose
template-parameter-list has a parameterdeclaration whose
type-specifier is either auto or a constrained-type-name.

[ Example:

auto f(auto x); // Ok
void sort(C& c); // Ok (assuming C names a concept)

— end example ]

This seems rather positive :)

followed by the excpected obvious wording, that matches generic lambda:

The declaration of a generic function has a template-parameter-list
that consists of one invented type template-parameter for each
occurrence of auto.

[ Example: The following generic function declarations are equivalent:

template<typenaem T>  
conxtexpr bool C() { ... }
auto f(auto x, const C& y);
template<typename T1, C T2>
auto f(T1 x, const T2& y);

The type of y is a type parameter constrained by C. — end example ]

Usage of auto concerning templates and functions

No.

  1. You need to explicitly use template, unless your compiler allows it as an extension. It might come in C++17.

    Is auto as a parameter in a regular function a GCC 4.9 extension?

  2. You probably want to take the functor/function-pointer by universal reference.

  3. You forgot to decay the vector's element-type.

  4. Your loop has a loop-variable of type int. Whether that is enough...

template<class F>
auto returnN(F&& gen, size_t n) {
std::vector<std::decay_t<decltype(gen())>> vec; // Needs to decay
while(n--)
vec.push_back(gen());
return vec;
}

Use of auto as return and parameters type in C++14

To start with, your code makes use of gcc extension, namely auto function parameters.

I guess your gcc version does not work with the extension properly and provides an incorrect result (with gcc 7.1 I have 0.67 0.67 even using auto parameters).

The normal way to rewrite your function in a standard C++ is to apply templates:

template<typename T, typename U>
auto multiplication(T a, U b)
{
return a * b;
}

and let the compiler to deduce return type.

Parameter packs and function declaration

Using auto as a function parameter is not Standard C++. Your code is currently not valid C++. See Is auto as a parameter in a regular function a GCC 4.9 extension? for more information. Note that auto as a function parameter (along with shorthand concept syntax) was not added to C++20's working draft yet.

Regardless, using auto in that manner is just shorthand for function template definition - this means that your need to define your function in the header.

Here's a solution that's valid C++:

// lib.h
template <typename... Js>
void funcN(int i, Js... js) {

}

More information: Why can templates only be implemented in the header file?

Are there negative ramifications of using auto as a parameter?

Yes, there are. They are forbidden by current C++ standard.

void Call( auto & fp )

is a compilation error on standard-conforming compiler.

Is this a bug in g++ c++14 support?

As stated by @SergeyA, this is a GCC bug. std::vector<auto> should not have been accepted.

auto type deduction for argument with default value


Should I be able to declare a function parameter as auto while still being able to give it a default value in C++11 or C++14?

I don't know if C++17 support it but, as far I know, C++11 and C++14 don't support an auto parameter for a function (C++14 support it only for lambda functions)

I thought the given default value would be enough to let compiler deduce the parameter type...

If instead of auto you accept to use a template type, you have to add the default template type also.

Something as follows

template <typename T = decltype(PrintColour::COLOUR_1)>
void colour( T c = PrintColour::COLOUR_1 )
{
switch ( c )
{
case PrintColour::COLOUR_1:
std::cout << "Colour 1" << std::endl;
break;
case PrintColour::COLOUR_2:
std::cout << "Colour 2" << std::endl;
}
}

I know: is redundant.

-- EDIT --

The OP says

I was just wondering if I couldn't make my code more readable by not repeating

More readable probably not but... if you want it not repeating... I know that macros are distilled evil but... if you really want avoid repeating...

#define noRepeat(r, n, a, b) \
r n (decltype(b) a = b)

noRepeat(void, colour, c, PrintColour::COLOUR_1)
{
switch ( c )
{
case PrintColour::COLOUR_1:
std::cout << "Colour 1" << std::endl;
break;
case PrintColour::COLOUR_2:
std::cout << "Colour 2" << std::endl;
}
}

or also (if you want make the trick on parameter basis)

#define parDef(a, b)  decltype(b) a = b

void colour ( parDef(c, PrintColour::COLOUR_1), parDef(d, 5) )
{
switch ( c )
{
case PrintColour::COLOUR_1:
std::cout << "Colour 1" << std::endl;
break;
case PrintColour::COLOUR_2:
std::cout << "Colour 2" << std::endl;
}
}


Related Topics



Leave a reply



Submit