I happened to come across the below code snippet in a video on C++11, where the author uses
auto main()->int
I didn't understand this. I tried to compile in g++ using -std=c++11 and it works.
Can somebody explain to me what is going on here? I tried to search using "auto main()->int" but didn't find any help.
C++11 introduced a notation for trailing return types: If a function declaration is introduced with auto, the return type will be specified after the parameters and a -> sequence. That is, all that does is to declare main() to return int.
The significance of trailing return types is primarily for function template where it is now possible to use parameters to the function together with decltype() to determine the return type. For example:
template <typename M, typename N>
auto multiply(M const& m, N const& n) -> decltype(m * n);
This declares the function multiply() to return the type produced by m * n. Putting the use of decltype() in front of multiply() would be invalid because m and n are not, yet, declared.
Although it is primarily useful for function template, the same notation can also be used for other function. With C++14 the trailing return type can even be omitted when the function is introduced with auto under some conditions.
This is a uniform function declaration syntax, trailing return type, introduced in C++11.
You can't use any other syntax for lamdas, and it's also very convenient for function templates where the result type depends on arguments.
If you want to select one single syntax (and I think that's a good idea), then you don't have any choice: the old syntax can't be used for lambdas.
Reason for doing that include:
Well, a single syntax.
Function name always at the same place visually, supports fast scanning of code.
Ditto for the result type, easy visual recognition (plus, you don't have to qualify it when it's a type defined in a member function's class).
Reasons against include some added verbosity, use of old compilers that don't understand this syntax, that anything new can feel scary and uncomfortable and just odd.
It is called trailing-return-type. It is particularly useful in generic codes using templates where the return type of depends on the expression involving some other template arguments. It is also used in lambda.
Here is an example:
template<typename T, typename U>
auto add(T t, U u) -> decltype(t+u)
{
return t + u;
}
Here the return type depends on the expression t+u. So whatever the type of the expression, is also the return-type of the function, which is indicated by decltype(t+u).
Related
I don't see the difference between these two, could someone tell me if there are differences?
template <typename Arg1>
void templatedFuncAlsoTakingAutoArg(Arg1 arg1, auto arg2)
{
// Both types are known at compile time for constexpr
static constexpr decltype(arg1) variable1 = decltype(arg1)();
static constexpr decltype(arg2) variable2 = decltype(arg2)();
// And both types work with constexpr if so that invalid code
// can appear within constexpr statements
// If I pass in a double for arg1 or arg2 this still compiles
if constexpr (std::is_integral_v<decltype(arg1)>)
{
arg1.non_existent_member = 7;
}
if constexpr (std::is_integral_v<decltype(arg1)>)
{
arg2.non_existent_member = 7;
}
}
What I'm wondering is basically if it came down to writing a function what would be the difference if I wrote it like this:
template <typename Arg>
void likeThis(Arg arg){}
or:
void orLikeThis(auto arg) {}
In the template version you have the advantage of being able to refer to the type directly, but in the 'auto' version you can always get the type with decltype anyway, right? So what are the differences? Under the hood is the version that takes auto actually a template anyway, and is instantiated in the same way the compiler does templates?
but in the 'auto' version you can always get the type with decltype anyway, right?
Not necessarily. Conceptually doesn't change nothing, but the template/typename version is a little more flexible.
See the generic lambdas, introduced in C++14 using auto instead the template/typename syntax.
In C++20 are introduced the template lambda because you can't do something as follows
[]<std::size_t ... Is>(std::index_sequence<Is...>)
{ return (Is + ...); }
(std::make_index_sequence<10u>{});
in a simple way, using auto.
EDIT: C++20 introduced the usage of auto as syntactic sugar for templates. The below would only apply to former C++ standards
It's important to remember, C++ is a statically typed language.
Using auto is like saying "figure out what type is suppose to go here and pretend like I wrote it out." This means that a variable with auto still will resolve to be a particular type. It does not mean that you can supply whatever type you want at runtime and expect it to figure it out, like you can with a dynamically typed language.
For that kind of functionality, you should use templates. But remember, you're still not supplying an arbitrary type at runtime and hoping that the code figures it out. At compile time, C++ needs to know what types you could use the function with, and then it will generate distinct versions of the function for those different types.
For example, if you used auto:
orLikeThis("one");
orLikeThis(1.0f);
...would fail to compile. The compiler has to assume that auto resolves to a single type, but since the code supplied both a string and a float, and now it can't resolve it to a single type.
However,
likeThis<string>("one")
likeThis<float>(1.1f)
Should compile. The compiler will create two different versions of the function to handle the different input types, but for convenience, you can simply provide a single function, and then just supply the type used.
So to answer your question of what the differences are, it comes down to how auto is syntactic sugar, and templates allow you to use multiple types in the "same" function.
TLDR; if you're looking to use multiple types, use a template; if you just want to avoid typing out the full type, then use auto. (Or if you're using C++20, auto will work for both use cases).
Auto keyword is used to infer the type of the variable based on the initialization. But I read on internet that auto can't determine the type of the function parameters. I didn't understand the reason why auto can't determine the type when used with function parameters. Can any one please let me know why auto can't be used with function parameters and any other cases where auto keyword can't be used to determine the type.
"Can't" is a strong word. After all, lambda parameters can use auto (in C++14). It's not so much "can't" as "doesn't". And perhaps "won't".
The question ultimately comes down to this: what does this actually do?
void foo(auto x)
{
std::cout << x << std::endl;
}
auto deduction is ultimately based on providing an initializing expression, which is used to deduce the actual type. This declaration contains no initializing expression.
C++ is a statically typed language; that means the compiler must be able to determine the type of every expression and object at compile time. From just the above, the compiler can deduce nothing.
So how can the compiler know that std::cout << x is legal C++ syntax? It can only tell that if there is an operator<< overload that takes std::cout and x. It can't figure out what is being called without first knowing the type of x. Which it doesn't; it can be different for different invocations of the function.
However, there is one C++ construct where the above makes sense: a template. This is exactly what using auto in lambda parameters does; it implicitly transforms the function into a template function. So [](auto x) {return x;} effectively becomes an operator something like this:
template<typename T>
auto operator()(T x) {return x;}
However, this conversion doesn't just fall out of having auto as a deduction syntax. It has to be something the standard is explicitly written to require. And, with the exception of C++14 generic lambdas, it doesn't.
Concepts TS includes this facility. However, this is merely an extension of the ability to use concepts in function parameter lists at all. That is, they already have a way to make a function implicitly create a template function, so they just added auto as essentially a case of "a concept that accepts any type".
But this was explicitly excluded from the C++20 version of concepts. The general reason for this exclusion is that, up until this point, template functions could be detected because they always had to have some special syntax. Namely, the inducer template<args>. With the Concepts TS version, there is concern that people will write template functions without realizing it.
And template functions behave differently from non-template functions. A template function is a family of functions, so you can't get a pointer to the family itself. You'd have to explicitly instantiate the template to get a pointer to that particular function.
So I understand using var in C# makes sense because you have anonymous types that are compiler derived. C++ doesn't seem to have this feature (unless I'm wrong), so what is the point of having an auto keyword?
(It is kinda cool that unlike C#, auto does work for member/global variables, which is cool I guess, but doesn't seem enough to justify its existence).
auto has a lot of uses when it comes down to both generic programming and to save the programmer some typing.
For example, consider this. Would you rather type out:
std::unique_ptr<name::long_type::goes_here> g =
std::make_unique<name::long_type::goes_here>(1,2,3,4)
or:
auto g = std::make_unique<name::long_type::goes_here>(1,2,3,4)
Yes, they're both long but we know the return type and specifying it again is a bit cumbersome to type. This also goes for iterators:
for(auto i = vec.begin(); ...)
vs:
for(std::vector<type>::iterator i = vev.begin(); ...)
Its use in generic programming is also to figure out the return type of a function or if you're doing some generic algorithms where you don't know the type.
For example, consider a very basic example.
template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) {
return t + u;
}
This allows the compiler to figure out the type of the add operation rather than us trying to figure it out ourselves. Note that in C++14 you can omit the trailing return type. Its uses in generic programming don't stop there either. If we wanted to work with any type of container as a wrapper function for algorithms we could use auto to help us with it. For example:
template<class Cont>
void my_sort(Cont&& cont) {
using std::begin;
auto first = begin(std::forward<Cont>(cont));
// work with the iterators here
}
In the future (C++14), auto can be used to make polymorphic lambdas as well such as:
[](auto a) { return a + 4; }
Which can be useful as well.
There are a number of uses for auto in C++
Anonymous function objects, aka closures, aka lambda instances. auto is the only way to store them. Types can also be generated derived off those types, and types on their backs, ad infinitum.
C++ can have quite complex types, such as the type of a non mutating iterator into an unordered map that uses a custom allocator and hashing function. typedef can mitigate this, but the type of a m.begin() having a particular name is not that informative: foo_iterator it = is as meaningful as auto foo_iterator =, and the auto one does not require boilerplate elsewhere.
Return type deduction uses the auto keyword, which is required to do some template functions work without huge amounts of traits boilerplate. Eliminating boilerplate is a common theme: C++s robust type system means that types can carry lots of information, and encoding it at every use can be counterproductive.
In some ducktype template code, the work to deduce the type of a variable is roughly the same as the work to code the variables value, and nearly identical in structure, some times literally: decltype(long expression) x = long expression;. auto eliminates that duplication.
Finally in C++1y, type deduction lambdas use auto to say that an argument is a deduced one. Sort of a light weight template. Talk to extend this to non lambdas is also in skunkworks.
HEre's a real life example where I could not, not use auto
I was trying to do a switch type statement in C++ where the return type is implementation specific and could not be declared easily. So using an 'auto' is probably the right way to resolve the type look up for the map declaration.
auto foo = boost::bind(&VegaFactory::load_commodity_one_leg,this,conn,_1);
std::map<std::string,decltype(foo)> methods;
methods.insert(std::make_pair("FOO",commodityOneLeg));
auto f = methods.find(bar);
// Call f here
C++ does have "anonymous" types - types you cannot refer to by name because the name is not available to you. This was the case even before C++11 and lambdas. Consider the following code:
class foo {
class bar {
public:
void baz() { }
};
public:
static bar func() { return bar(); }
};
foo::func().baz(); // OK, only the name "bar" is private
??? a = foo::func(); // Umm...
auto b = foo::func(); b.baz(); // Hooray!
Even if not actually declared in a private scope, it is often useful for a library to leave some types unspecified in its API - especially when heavily utilizing expression templates or other template metaprogramming where the type names can be arbitrarily long with all the nested template arguments. Even the standard itself does this - for instance, the result type of std::bind is not defined by the specification.
syntactic sugar
I rather say
auto i = mapping.begin();
over
std::map<int, int>::iterator i = mapping.begin();
It is well worth reading Herb Sutter's article Almost Always Auto for some great examples of why it's worth using auto over explicit types. The main advantages are the reduction in typing, and gives additional safety if the underlying types change. One of my favourite examples though is about how it reduces duplication. If you allocate on the stack then you'd use:
MyClass c(param);
However, if you want to create on the heap you need:
MyClass* c=new MyClass(param);
So you've had to duplicate the MyClass, but the RHS already forces the variable to be a MyClass pointer, so you can just use this instead:
auto c=new MyClass(param);
If you want to declare it as a unique_ptr then previously you would need:
unique_ptr<MyClass> c=make_unique<MyClass>(param);
which can be abbreviated to:
auto c=make_unique<MyClass>(param);
In C++, auto keyword provides a way of type deduction mechanism. For example,
auto i = expressions;
auto keyword tells the compiler to determine the type of variable i from the expression on the right side of the assignment operator.
Therefore if the value of expressions is double, then variable i will be double. Or, if the value of expressions is bool, then variable i will be bool.
so, let's learn type inference first which is basically refers to automatic deduction of the data type of an expression in a programming language.
before C++ 11 all the variables in c++ have to explicitly declare but after the release of c++ 11, the compiler itself deduces the type of the variable at runtime.
we can use it for variables and even in the case of function return types.
but, it's suggested to avoid using auto in function return type.
I understand that using templates is one of the appreciated way of overloading but i was wondering why auto cannot be used for function parameter type deduction hence aiding overloading of the function?
N3690 says in 7.6.1.4/3 that lambda expression can be made generic using auto,providing this example
auto glambda = [](int i, auto a) { return i; };//OK: a generic lambda
(note: this is not mentioned in N3485)
1).why cant i do a similar thing for a normal function for e.g
void swap(auto& param1, decltype(param1)& param2)
{
decltype(param1) temp = param1;
param1 = param2;
param2 = temp;
}
this gives errors error : parameters declared auto.
from N3690 7.1.6.4/4
The type of a variable declared using auto or decltype(auto) is deduced from its
initializer. This use is allowed when declaring variables in a block (6.3), in namespace scope (3.3.6), and in a for-init-statement (6.5.3).[...]
am i wrong in assuming that the param1 and param2 fall under block scope and hence eligible for auto deduction?
2). if such feature was allowed what would be the pitfalls?
i'm using gcc 4.8.1.
Thank you
n3690 7.1.6.4/2
The placeholder type can appear with a function declarator in the decl-specifier-seq, type-specifier-seq,
conversion-function-id, or trailing-return-type, in any context where such a declarator is valid.
7.1.6.4/3
If the auto type-specifier appears as one of the decl-specifiers in the decl-specifier-seq of a parameter-
declaration of a lambda-expression, the lambda is a generic lambda.
7.1.6.4/4
The type of a variable declared using auto or decltype(auto) is deduced from its initializer. This use is al-
lowed when declaring variables in a block (6.3), in namespace scope (3.3.6), and in a for-init-statement (6.5.3).
auto or decltype(auto) shall appear as one of the decl-specifiers in the decl-specifier-seq and the decl-
specifier-seq shall be followed by one or more init-declarators, each of which shall have a non-empty initial-
izer.
7.1.6.4/5
A placeholder type can also be used in declaring a variable in the condition of a selection statement (6.4) or
an iteration statement (6.5), in the type-specifier-seq in the new-type-id or type-id of a new-expression (5.3.4), in
a for-range-declaration, and in declaring a static data member with a brace-or-equal-initializer that appears
within the member-specification of a class definition (9.4.2).
Only such usage is alowed. Any other usage is prohibited (in particular usage in parameter-declaration-clause).
7.1.6.4/6
A program that uses auto or decltype(auto) in a context not explicitly allowed in this section is ill-formed.
N3690 is the committee draft for C++14, i.e. for the next C++ standard that has yet to be released and wich might not be implemented yet in most compilers. So you should refer to your compiler's documentation if generic lambdas are implemented - I guess they are not.
However, with gcc you have good chances that C++14 features will be implemented before the new standard is officially released, though you might have to explicitly enable C++14 support with a command line flag. Looking at the docs it should be -std=gnu++1y
According to this site, generic lambdas are not implemented yet in GCC.
Update:
As for normal generic functions using auto parameters: These don't exist and won't be coming for the next time. The reason is that templated functions are only slightly more verbose to type and more powerful, since you can refer to the types and directly apply template metafunctions to them. In generic lambdas this can be done only by using decltype(a), wich is a bit more tedious and has to be used with care, because it behaves a bit different than template argument deduction.
An additional bonus with templates compared to auto params is a bit more typesafety or expressiveness:
void func(auto a, auto b); //a and b might be different types
template <class T>
void func(T a, T b); //a and b must be the same type
On top of ForEveR's answer:
Why cant i do a similar thing for a normal function for e.g
void swap(auto& param1, decltype(param1)& param2)
Simply because the language doesn't allow this. Before auto was (re)invented in C++11 what you want was achievable through templates:
template <class T, class U>
void swap(T& param1, U& param2);
C++11 also brough lambda expressions and C++14 is likely to introduce polymorphic lambdas which are, basically, lambdas whose operator () are templates. A syntax similar to that of templates was considered for the polymorphic lambdas, for instance (example taken from N3418)
[]<class T>(T* p) { /* ... */ }
At the end, the prefered syntax was using auto rather than introducing a template parameter list.
It's true that one could consider extend this terser syntax to function templates (as the OP suggests) but, as far as I know, the committee hasn't considered this possibility. It might do in the future but someone has to formally propose it. This might be a "nice feature to have" but IMHO this is just syntactic sugar that doesn't bring much to the language.
Also, I can't see how this terser syntax (with no template parameter lists) could be used for template classes and perhaps diverging the syntax for template functions from that of template classes is not worth doing.
There is already a way to write what you wanted :-
template <class T>
void swap(T& param1, T& param2)
{
T temp = param1;
param1 = param2;
param2 = temp;
}
So why create a new syntax that doesn't let you do anything you couldn't do before. The suggested change to lambdas are to allow generic lambdas which you couldn't do before, and I guess any syntax using the template syntax would have been ugly here.
While reading Wikipedia's page on decltype, I was curious about the statement,
Its [decltype's] primary intended use is in generic
programming, where it is often
difficult, or even impossible, to name
types that depend on template
parameters.
While I can understand the difficulty part of that statement, what is an example where there is a need to name a type that cannot be named under C++03?
EDIT: My point is that since everything in C++ has a declaration of types. Why would there ever be a case where it is impossible to name a type? Furthermore, aren't trait classes designed to yield type informations? Could trait classes be an alternative to decltype?
The wikipedia page you link has a perfect example:
int& foo(int& i);
float foo(float& f);
template <class T> auto transparent_forwarder(T& t) −> decltype(foo(t)) {
return foo(t);
}
Note that foo(int&) returns int& (a reference type) while foo(float&) returns float (a nonreference type). Without decltype, it's impossible within the template to specify a type which represents "the return type of the function foo which takes an argument t of type T".
In this example, it's not a particular concrete type which is impossible to express -- either int& or float are individually expressible -- but a higher level generic class of types.
EDIT: and to answer your comment to another answer, this example is inexpressible in C++03. You cannot have a function template which will wrap any function T1 foo(T2) and match both argument and return type of the wrapped function.
There are types in C++0x (and in C++03, but less often) that cannot be named explicitly, such as the type decltype(f) after the declaration auto f = [](int x) -> int {return x;};. You would need to typedef that decltype result to something to get a name at all. Traits classes can be used for determining return types, but they are messy, and the user needs to duplicate all of their function overloads with traits class overloads; that is difficult to do correctly for cases such as functions applying (through implicit conversion of pointers) to all subclasses of a given base class.
As you pointed out, the type if it exist is known by the compiler, otherwise it wouldn't exist. However, it is not always readily or even accessible to the programmer in C++03.
N1607 mention the following in its conclusion:
In C++2003, it is not possible to
express the return type of a function
template in all cases. Furthermore,
expressions involving calls to
function templates commonly have very
complicated types, which are
practically impossible to write by
hand
The question is how do we access this type as a programmer. This is not always a trivial process, often impracticable. It is increasingly complex when you have an expression for which you desire to know the result type. You would have to break it into pieces in order to figure the result types. It is not possible to simplify this process using templates (not without evaluating the expression anyhow). Breaking the expression will be error-prone, tedious and a nightmare to maintain. Think of this code:
x.g()[b.a(e)]->f();
With C++98/TR1, it is often infeasible to name types that depend on template parameters. Traits offers us so much information, but eventually decltype is a much cleaner solution to many problems. A lot of the information available to you when meta programming is only available because libraries, such as boost or loki, use several tricks hidden in the dark corners of the C++98 language.
Of course this is irrelevant to your question but I believe that it is worthy to mention that C++98 compilers already have mechanics to know these types. This is exactly what sizeof offers, except that it returns you a size. decltype reuse some of this functionality and solves these problems with greater elegance.
As for a different (academic) example:
struct Foo
{
struct
{
int x;
} bar;
};
template<typename T>
void
f(const T& t)
{
// C++03, How can I name the type of T::bar ?
// C++0x
// decltype(t.bar) cpy;
// Do stuff with our local cpy
}
int
main()
{
f(Foo());
}