I have a question about overloading operator <>. I read some C++ books and I do not understand that why do we use friend function for overloading operator <> instead of defining it as a member function of the class.
Related
I have a wrapper class that needs to be used interchangeably with the wrapped class.
Fortunately the class and the wrapper are binary compatible (by design) and the conversion can be easily performed (for example in this case by reinterpret_cast, or even simpler as in the example).
In part, to achieve this, I need to be able to convert from the wrapper type to the wrapped type, via operator T().
Currently the code looks like this:
template<class T> // // I am putting this general T type, to show it can be a large (movable) object, for example, std::vector.
struct wrapper{
T a;
operator T const&() const&{return a;} // in other cases it can involve more code, like reinterpret_casts or some conditional blocks.
operator T&&() &&{return std::move(a);} // same
operator T&() &{return a;} // same
};
Can I condense these three conversion functions into one function or less code, or is there another way?
I could make it more general, (but longer code for this simple case) this way,
template<class T>
struct wrapper{
T a;
operator T const&() const&{return a;} // complicated code can be here only
operator T&&() &&{return std::move(operator A&());}
operator T&() &{return const_cast<T&>(operator T const&());}
};
The final objective is that T can be used interchangeably with wrapper<T>.
This is very similar to How do I remove code duplication between similar const and non-const member functions?,
however this case is more specific because 1) it involves the conversion operator and also, 2) involves l-value overloads.
I've seen many examples of using a lambda expression as a template argument, but when i was reading the reference page for lambda functions at cppreference.com,
it has this short sentence:
Lambda-expressions are not allowed in unevaluated expressions, template arguments, alias declarations, typedef declarations, and anywhere in a function (or function template) declaration except the function body and the function's default arguments.
I was very confused, is this sentence wrong or I did not understand it correctly?
What you can do:
template <class>
struct Foo;
auto l = []{};
Foo<decltype(l)> f;
What you cannot do:
template <SomeType lambda>
struct Foo;
Foo<[]{}> f;
In other words, the type of the lambda is a normal type like any other, but the lambda-expression itself can't be used to specialize a template. The same applies to unevaluated contexts such as the operands of decltype and sizeof.
I am curious why, in C++ 11, use of "= default" on a derived virtual method does not select the pure base class implementation.
For example, the following test code produces the message "error: 'virtual void B::tst()' cannot be defaulted" from "g++ -std=c++11".
struct A {
virtual ~A () = default;
virtual void tst () = 0;
};
void A :: tst () {}
struct B : public A {
virtual void tst () = default;
};
We can of course provide a B::tst that invokes the default base implementation, but one is concerned that this might be the higher overhead implementation compared to a hypothetical "= default" based coding.
Sorry to ask questions about what might or might not be within the minds of the c++ standards committee persons, but nevertheless perhaps someone here at stack overflow will have some wisdom concerning the impracticality of using the default keyword in this way that would be interesting to hear.
Thanks!
According to the standard §8.4.2/p1 Explicitly-defaulted functions [dcl.fct.def.default] (Emphasis Mine):
A function definition of the form:
attribute-specifier-seqopt decl-specifier-seqopt declarator
virt-specifier-seqopt = default;
is called an explicitly-defaulted definition. A function that is
explicitly defaulted shall
(1.1) — be a special member function,
(1.2) — have the same declared function type (except for possibly differing ref-qualifiers and except that in
the case of a copy constructor or copy assignment operator, the parameter type may be “reference to
non-const T”, where T is the name of the member function’s class) as if it had been implicitly declared,
and
(1.3) — not have default arguments
Member function tst() is not a special member function. Thus, it cannot be defaulted.
Now specifying a member function of a class (e.g., class A) as pure virtual entails that any class that inherits from that class and you don't wan't it to be abstract as well must override that member function.
I am fimilar with std::function , but i am reading a book that there is a code like this :
template<typename GameObject, typename Function>
std::function<void(SceneNode&, sf::Time)> derivedAction(Function fn)
{
return [=](SceneNode& node, sf::Time dt)
{
assert(dynamic_cast<GameObject *>(&node) != nullptr);
fn(static_cast<GameObject *>(&node), dt)
}
}
then the book use template like this :
Command moveLeft;//command is a structure
moveLeft.action//action is a std::function object
= derivedAction<Aircraft>(AircraftMover(-playerSpeed, 0));
//derivedAction specify<Aircraft> ???
my questions are :
1-derivedAction must be an object of std::function , i have checked references but i haven't found this kind of initialazation with {} , how this works ?
2-it is complicated to me , to understand the lambda expression , and why there is a return for it ?
i am pretty confused about this peice of code , any explination would be appreciated
std::function is a wrapper around anything, that can be called (i.e, you can use operator() on it). That is pointer to a function, class having operator() overloaded or lambda expression.
In your case, derivedAction is a templated function, accepting a single parameter (of templated type of name Function) and returning a function having void return type and accepting two parameters -- SceneNode& and sf::Time.
So to answer your questions.
1-derivedAction must be an object of std::function , i have checked references but i haven't found this kind of initialazation with {} , how this works ?
No, derivedAction is a function itself, like any other (i.e. int foo(){ return 0; }).
2-it is complicated to me , to understand the lambda expression , and why there is a return for it ?
Once again, the return value of derivedAction is a function (or rahter, something, which is callable).
If you look closely to the code of derivedAction, you will see, that it only wraps a function Function fn with some checks.
For your first question, derivedAction is a function, so you could define an empty body {} just like with any other function.
As for your second question, the return is the return of derivedAction. The breakdown of the lambda is as follows:
[=] Instructs to capture any referenced variable by making a copy
(SceneNode& node, sf::Time dt) describes the input arguments of the lambda function
In the body of the lambda, the lambda function operates on fn(). It casts node to a different type and modifies the node object.
In your example, fn is AircraftMover(-playerSpeed, 0). playerSpeed is of type SceneNode&, and 0 is of type sf::Time. The return type of that function is void. So, what all of this does in the end is modify the playerSpeed you feed into it based on dt. Hope this makes sense..!
In this sample:
auto f = [](int some, int some2){
//do something
};
This case it is a functor or object of function?
std::function<void(int, int)> f = [](int some, int some2) {
//do something
}
Now, in this case, whats is the results? Functor or Object of function?
The first f (i.e., the one designated with auto) results to what is called a lambda function. Also knows as a closure. Closures are unnamed function objects. That's why we need auto to deduce the type of a closure. We don't know it's type but the compiler does. Thus, by using auto we let the compiler deduce the type of the unnamed closure object for us.
The second f (i.e., the one designated with std::function) is a std::function object. Class std::function is a general-purpose polymorphic function wrapper.
Lambdas closures as function objects can be converted to their respective std::function objects. That is exactly what is happening in:
std::function<void(int, int)> f = [](int some, int some2) {
//do something
}
The lambda closure on the right hand side is assigned and converted to the std::function object on the left side of the assignment.
Practically, they're both interpreted as functors, since they both overload call operator() and thus can be called, except for that the lambda's type is unnamed.
Another difference between those two is that you can't assign between lambda closures, since for lambda closures the assignment operator is declared deleted. while you can assign between std::function objects.