This question already has answers here:
Should the trailing return type syntax style become the default for new C++11 programs? [closed]
(4 answers)
Closed 6 years ago.
I've seen in an article a code similar to this one:
#include <iostream>
class MyClass {
public:
auto myFunction(int i)->void {
std::cout << "Argument is " << i << std::endl;
}
};
void main() {
MyClass myClass;
myClass.myFunction(4);
}
The program prints correctly the output Argument is 4, but I don't understand the signature of the class function member and what's its difference with the usual one. When it's useful to use this different signature rather than void myFunction(int i)?
This is an (ab)use of the trailing-return-type syntax that has been introduced in C++11. The syntax is:
auto functionName(params) -> returnType;
auto functionName(params) -> returnType { }
It works the same as a classic function declaration with the return type on the left, except that the trailing type can use names introduced by the function's signature, i.e:
T Class::function(param); // No particular behaviour
auto Class::function(param) -> T; // T can use Class::Foo as Foo, decltype(param), etc.
In this case though, there is no point except consistency.
Related
This question already has answers here:
How does generic lambda work in C++14?
(4 answers)
Generic lambdas Vs Standard template functions (What to use and When)
(1 answer)
Closed 8 months ago.
Here is a code snippet I have created:
auto f = [](auto a) -> auto {
cout << a << endl;
return a;
};
cout << f(12) << endl;
cout << f("test");
Here is what I know: Types have to be all resolved / specified at compile time.
The question here is, how is the compiler behaving when it sees this lambda function f? How does it deduces all the types for specific use like in line 6 and 7, in which we can see there are two different arguments passed for each call of lambda function f. Is the compiler creating different instances of the lambda function f to match the types passed?
Any help will be appreciated!
Also, if the answer is going to be too technical to be written on a few lines, I'd appreciate for any good reference on lambda functions and how they work.
One thing I have noticed, is that auto is not allowed when defining functions the usual way:
void f(auto a)
{
}
this does not compile.
Lambda is mostly equivalent to functor class:
struct Lambda
{
template <typename T>
auto operator()(T a) const
std::cout << a << std::endl;
return a; // make auto deduce as T
}
};
f(12) would instantiate Lambda::operator()<int>
and f("test") would instantiate Lambda::operator()<const char*>.
This question already has answers here:
Resolving ambiguous overload on function pointer and std::function for a lambda using + (unary plus)
(1 answer)
A positive lambda: '+[]{}' - What sorcery is this? [duplicate]
(1 answer)
Closed 1 year ago.
I found out that in C++ we can use + in lambda function +[]{}
Example from the article:
#include <iostream>
#include <type_traits>
int main()
{
auto funcPtr = +[] {};
static_assert(std::is_same<decltype(funcPtr), void (*)()>::value);
}
The main idea of + sign in lambda
You can force the compiler to generate lambda as a function pointer rather than closure by adding + in front of it as above.
But what are advantages of using '+' in lambda? Could you please provide example or link me to the explanation?
It's not a feature of lambda and more is a feature of implicit type conversion.
What happens there is stemming from the fact that a captureless lambda can be implicitly converted to a pointer to function with same signature as lambda's operator(). +[]{} is an expression where unary + is a no-op , so the only legal result of expression is a pointer to function.
In result auto funcPtr would be a pointer to a function, not an instance of an object with anonymous type returned by lambda expression. Not much of advantage in provided code, but it can be important in type-agnostic code, e.g. where some kind of decltype expression is used. E.g.
#include <type_traits>
void foo(int);
template<class T>
struct is_foo : std::is_same<T, decltype(&foo)> {};
int main()
{
auto foo1 = +[](int)->void {};
auto foo2 = [](int)->void {};
static_assert(is_foo<decltype(foo1)>::value, "foo1 is not like foo");
static_assert(is_foo<decltype(+foo2)>::value, "+foo2 is not like foo");
static_assert(is_foo<decltype(foo2)>::value, "foo2 is not like foo");
}
Note that you can do same with foo: std::is_same<T, decltype(+foo)> {};
Albeit some platforms may not support that, because they inherently may have a variety of function pointers with different calling convention and the expression will be ambiguous.
One advantage to use function pointer against lambda in template might be to reduce the number of template instantiation.
template <typename F>
void f(F func) { func(); }
int main()
{
f([](){}); // f<lambda_1>
f([](){}); // f<lambda_2>
f(+[](){}); // f<void(*)()>
f(+[](){}); // f<void(*)()>
}
This question already has an answer here:
type defined in free function, accessible through auto outside. Language Bug or Feature?
(1 answer)
Closed 4 years ago.
Is the following code valid according to (any) C++ ISO standards?
#include <functional>
auto a() {
struct Foo {
};
return []() {return Foo{}; };
}
int main()
{
auto l = a()();
decltype(l) ll;
//Foo f; //error: unknown type name 'Foo'
return 0;
}
The compilers (Visual studio 2015, latest Clang and latest GCC) accept this but it seems weird that decltype should give me access to Foo.
Yes.
It is actually the name of the type that is scoped, not the type itself.
You're not using its name, so everything is fine.
This question already has answers here:
C++0x const RValue reference as function parameter
(2 answers)
Closed 5 years ago.
Recently i accidently programmed the following:
void someFunction(const SomeClass&& value){
//Some Code
}
I didn't mean to add the 'const' keyword to the value parameter. However, this made me think: is it even possible to somehow call this function, if an equivalent function without const exists? If yes, does this ever make sense and is there some practical use to it?
This code:
#include <iostream>
using namespace std;
struct s{};
void someFunction(s& value){ std::cout << "ref" << std::endl; }
void someFunction(const s&& value){ std::cout << "const" << std::endl; }
void someFunction(s&& value){ std::cout << "non const" << std::endl; }
const s foo() { return s(); }
s bar() { return s(); }
int main() {
someFunction(bar());
someFunction(foo());
return 0;
}
Prints
non const
const
For some explanation (that I cannot provide ;) I refer you to this site. The most relevant quote is:
[...] This makes const rvalue references pretty useless. Think about it: if
all we need is a non-modifiable reference to an object (rvalue or
lvalue), then a const lvalue reference does the job perfectly. The
only situation where we want to single out rvalues is if we want to
move them. And in that case we need a modifiable reference.
The only use case I could imagine is to use someFunction to detect whether a second function returns a const or a non-const, but I guess there are easier ways to find that out.
As a sidenote: When you replace s with int in above code it prints:
non const
non const
and that is because (quoting from the same site, comment from pizer):
There are no const prvalues of scalar types. For a const rvalue you
either need an Xvalue and/or a class-type object. [...]
This question already has answers here:
How to correctly use std::reference_wrappers
(2 answers)
Closed 4 years ago.
I don't understand exactly why one cannot use a std::reference_wrapper like this:
#include <vector>
#include <functional>
struct Foo
{
void f() {};
};
int main()
{
std::vector<std::reference_wrapper<Foo>> vrFoo;
Foo foo;
vrFoo.push_back(foo);
// vrFoo[0].f(); // error
vrFoo[0].get().f(); // or static_cast<Foo&>(v[0]).f();
}
Why do we have to use the get() member function? It looks like std::reference_wrapper has an implicit conversion to T& via operator T&() const noexcept, see http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper
so why isn't v[0] implicitly converted to a reference?
In other situations, such as
std::cout << v[0] << std::endl
this conversion takes place (I assume here that Foo overloads operator<<)
Because . is always used to access members of the object it's applied to. Type conversions aren't considered.
There's a proposal to allow overloading of operator., to enable exactly what you want, but that won't be standard until at least C++17, if at all.
This is a language limitation as #MikeSeymour pointed out.
And this is the reason why I think std::reference_wrapper should have an overloaded operator& that returns the address of the wrapped object:
template<class T>
struct reference_wrapper{
...
T* operator &(){return ptr;}
}
So that later one can use &Foo->f() or (*&Foo).f() instead of Foo.get().f() or static_cast<T&>(Foo).f().