I recently discovered that in C++ you can overload the "function call" operator, in a strange way in which you have to write two pair of parenthesis to do so:
class A {
int n;
public:
void operator ()() const;
};
And then use it this way:
A a;
a();
When is this useful?
This can be used to create "functors", objects that act like functions:
class Multiplier {
public:
Multiplier(int m): multiplier(m) {}
int operator()(int x) { return multiplier * x; }
private:
int multiplier;
};
Multiplier m(5);
cout << m(4) << endl;
The above prints 20. The Wikipedia article linked above gives more substantial examples.
There's little more than a syntactic gain in using operator() until you start using templates. But when using templates you can treat real functions and functors (classes acting as functions) the same way.
class scaled_sine
{
explicit scaled_sine( float _m ) : m(_m) {}
float operator()(float x) const { return sin(m*x); }
float m;
};
template<typename T>
float evaluate_at( float x, const T& fn )
{
return fn(x);
}
evaluate_at( 1.0, cos );
evaluate_at( 1.0, scaled_sine(3.0) );
A algorithm implemented using a template doesn't care whether the thing being called is a function or a functor, it cares about the syntax. Either standard ones (e.g. for_each()) or your own. And functors can have state, and do all kinds of things when they are called. Functions can only have state with a static local variable, or global variables.
If you're making a class that encapsulates a function pointer, this might make the usage more obvious.
The compiler can also inline the functor and the function call. It cannot inline a function pointer, however. This way, using the function call operator can significantly improve performance when it is used for example with the standard C++ libary algorithms.
For example for implementing generators:
// generator
struct Generator {
int c = 0;
virtual int operator()() {
return c++;
}
};
int sum(int n) {
Generator g;
int res = 0;
for( int i = 0; i < n; i++ ) {
res += g();
}
return res;
}
I see potential to yet one exotic use:
Suppose you have object of unknown type and have to declare another variable of same type, like this:
auto c=decltype(a*b)(123);
When such pattern used extensively, decltype become very annoying.
This case can occur when using some smart type system that automatically invent type of result of functions and operators based on types of arguments.
Now, if each specialization of each type of that type system equipped with
magic definition of operator() like this:
template<????> class Num<???>{
//specific implementation here
constexpr auto operator()(auto...p){return Num(p...);}
}
decltype() no more needed, you can write simply:
auto c=(a*b)(123);
Because operator() of object redirects to constructor of its own type.
Related
I have the situation where one function calls one of several possible functions. This seems like a good place to pass a function as a parameter. In this Quoara answer by Zubkov there are three ways to do this.
int g(int x(int)) { return x(1); }
int g(int (*x)(int)) { return x(1); }
int g(int (&x)(int)) { return x(1); }
...
int f(int n) { return n*2; }
g(f); // all three g's above work the same
When should which method be used? What are there differences? I prefer the simplest approach so why shouldn't the first way always be used?
For my situation, the function is only called once and I'd like to keep it simple. I have it working with pass by pointer and I just call it with g(myFunc) where myFunc is the function that gets called last.
Expanding on L.F.'s comment, it's often better to eschew function pointers entirely, and work in terms of invocable objects (things which define operator()). All of the following allow you to do that:
#include <type_traits>
// (1) unrestricted template parameter, like <algorithm> uses
template<typename Func>
int g(Func x) { return x(1); }
// (2) restricted template parameter to produce possibly better errors
template<
typename Func,
typename=std::enable_if_t<std::is_invocable_r_v<int, Func, int>>
>
int g(Func x) { return std::invoke(x, 1); }
// (3) template-less, trading a reduction in code size for runtime overhead and heap use
int g(std::function<int(int)> x) { return x(1); }
Importantly, all of these can be used on lambda functions with captures, unlike any of your options:
int y = 2;
int ret = g([y](int v) {
return y + v;
});
Please consider the following code:
#include <iostream>
#include <unordered_set>
struct MyStruct
{
int x, y;
double mutable z;
MyStruct(int x, int y)
: x{ x }, y{ y }, z{ 0.0 }
{
}
};
struct MyStructHash
{
inline size_t operator()(MyStruct const &s) const
{
size_t ret = s.x;
ret *= 2654435761U;
return ret ^ s.y;
}
};
struct MyStructEqual
{
inline bool operator()(MyStruct const &s1, MyStruct const &s2) const
{
return s1.x == s2.x && s1.y == s2.y;
}
};
int main()
{
std::unordered_set<MyStruct, MyStructHash, MyStructEqual> set;
auto pair = set.emplace(100, 200);
if (pair.second)
pair.first->z = 300.0;
std::cout << set.begin()->z;
}
I am using mutable to allow modification of the member z of MyStruct. I would like to know if this is ok and legal, since the set is a) unordered and b) I am not using z for hashing or equality?
I would say this is a perfect use of the "Mutable" keyword.
The mutable keyword is there to mark members that are not part of the "state" of the class (ie they are some form of cached or intermediate value that does not represent the logical state of the object).
Your equality operator (as well as other comparators (or any function that serializes the data) (or function that generates a hash)) define the state of the object. Your equality comparitor does not use the member 'z' when it checks the logical state of the object so the member 'z' is not part of the state of the class and is therefore illegable to use the "mutable" accessor.
Now saying that. I do think the code is very brittle to write this way. There is nothing in the class that stops a future maintainer accidentally making z part of the state of the class (ie adding it to the hash function) and thus breaking the pre-conditions of using it in std::unordered_set<>. So you should be very judicious in using this and spend a lot of time writing comments and unit tests to make sure the preconditions are maintained.
I would also look into "#Andriy Tylychko" comment about breaking the class into a const part and a value part so that you could potentially use it as part of a std::unordered_map.
The problem is that z is not part of the state of the object only in the context of that particular kind of unordered_set.
If one continues this route one will end up making everything mutable just in case.
In general, what you are asking is not possible because the element hash would need to be recomputed automatically on the modification of the element.
The most general thing you can do is to have a protocol for element modification, similar to the modify function in Boost.MultiIndex https://www.boost.org/doc/libs/1_68_0/libs/multi_index/doc/reference/ord_indices.html#modify.
The code is ugly, but thanks to the existence of extract it can be made fairly efficient when it matters (well, still your particular struct will not benefit from move).
template<class UnorderedSet, class It, class F>
void modify(UnorderedSet& s, It it, F f){
It h = it; ++h;
auto val = std::move(s.extract(it).value());
f(val);
s.emplace_hint(h, std::move(val) );
}
int main(){
std::unordered_set<MyStruct, MyStructHash, MyStructEqual> set;
auto pair = set.emplace(100, 200);
if (pair.second) modify(set, pair.first, [](auto&& e){e.z = 300;});
std::cout << set.begin()->z;
}
(code not tested)
#JoaquinMLopezMuños (author of Boost.MultiIndex) suggested reinserting the whole node. I think that would work like this:
template<class UnorderedSet, class It, class F>
void modify(UnorderedSet& s, It it, F f){
It h = it; ++h;
auto node = s.extract(it);
f(node.value());
s.insert(h, std::move(node));
}
EDIT2: Final tested code, needs C++17 (for extract)
#include <iostream>
#include <unordered_set>
struct MyStruct
{
int x, y;
double z;
MyStruct(int x, int y)
: x{ x }, y{ y }, z{ 0.0 }
{
}
};
struct MyStructHash
{
inline size_t operator()(MyStruct const &s) const
{
size_t ret = s.x;
ret *= 2654435761U;
return ret ^ s.y;
}
};
struct MyStructEqual
{
inline bool operator()(MyStruct const &s1, MyStruct const &s2) const
{
return s1.x == s2.x && s1.y == s2.y;
}
};
template<class UnorderedSet, class It, class F>
void modify(UnorderedSet& s, It it, F f){
auto node = s.extract(it++);
f(node.value());
s.insert(it, std::move(node));
}
int main(){
std::unordered_set<MyStruct, MyStructHash, MyStructEqual> set;
auto pair = set.emplace(100, 200);
if(pair.second) modify(set, pair.first, [](auto&& e){e.z = 300;});
std::cout << set.begin()->z;
}
The typical used mutable is to allow a const method to change a data member that does not form part of an object’s fundamental state e.g. a lazily evaluated value derived from the object’s non-mutable data.
Declaring public data members mutable is not good a practice, you are allowing the objects state to be changed externally even when that object is marked const.
In your example code, you have used mutable because (based on your comment), your code would not compile without it. Your code would not compile because the iterator returned from emplace is const.
There are two incorrect ways to solve this problem, one is the use of the mutable keyword, another, almost as bad, is to cast the const reference into a non-const reference.
The emplace method is intended to construct an object directly into the collection and avoid a copy constructor call. This is a useful optimization but you shouldn’t use it if it will compromise the maintainability of your code. You should either initialize z in your constructor or you should not use emplace to add the object to the set, instead set the value of z and then insert the object into your set.
If your object never needs to change after construction, you should make your class/struct immutable by either declaring them const or declaring the data members private and adding non-mutating accessor methods (these should be declared const).
Prelude: I have updated this question to address NicolBolas' suggestion. Please leave a constructive comment if you downvote, thank you.
I'm writing a function that takes a number (uint) or a flag that it's not a number. It then goes on to work with the given number or -1.
Here's the idea
struct Numeric {
virtual int to_int() const = 0;
};
struct NotANumber : Numeric {
int to_int () const {
return -1;
}
}
struct Number : Numeric {
const uint n;
Number (const uint n): n(n) {}
int to_int () const {
return n;
}
};
So then my function could be used as:
calculate_stuff(NotANumber());
calculate_stuff(Number(4));
My question is whether it's possible to move the to_int method outside of the classes, into the form of an overloaded function:
struct Numeric {};
struct NotANumber : Numeric {}
struct Number : Numeric {
const uint n;
Number (const uint n): n(n) {}
};
int Numeric_to_int (const NotANumber) {
return -1;
}
int Numeric_to_int (const Number n) {
return n.n;
}
This doesn't seem to work. Is it possible to fix this? Is the issue that overloading happens at compile time, whereas overriding is at runtime?
(I think I'm going to use std::optional and value_or for this specific problem, but I would still like to know the answer to my questions above)
Edit: sorry, I should've clarified what "doesn't work" means:
int calculate_stuff (const Numeric n) {
std::cout << Numeric_to_int(n) << std::endl;
return 0;
}
This doesn't compile: no matching function for call to ‘Numeric_to_int(const Numeric&)’
int calculate_stuff (const Numeric n)
How could it work? You passed in a base class. By value. The compiler cannot know what derived class it used to be. In fact, since you took the base class by value, the compiler knows that n is neither of the derived classes.
C++ isn't Java; if you pass something by value, you make a copy (or move to it). And if you passed one of the derived classes, that causes slicing; you only copy the base class data. The parameter is therefore exactly what it says: an object who's dynamic type is Numeric. Exactly and only that, not one of its derived classes.
Even if you took a const Numeric &n instead, that won't help. The compiler doesn't know what type it used to be. And you can't even use dynamic_cast to convert it back, since Numeric is not a polymorphic class.
A better way to handle this is to actually use a proper variant class (optional is effectively a specialized variant).
My question is whether it's possible to move the to_int method outside of the classes, into the form of an overloaded function.
Using overloaded non-member functions is a viable option only if you deal with the derived types at all times.
If you need the functionality through a reference or pointer to the base class type, then using overloaded non-member functions is not a viable option. In that case, a virtual member function is the right choice.
You can use a template class and an using declaration to do that:
template<int v>
struct Numeric {};
using NotANumber = Numeric<-1>;
template<int N>
constexpr int Numeric_to_int (Numeric<N>) {
return N;
}
int main() {
static_assert(Numeric_to_int(NotANumber{}) == -1, "!");
static_assert(Numeric_to_int(Numeric<42>{}) == 42, "!");
}
Also, consider the use of a std::integral_constant for the same purpose.
As an example:
template<int v>
using Numeric = std::integral_constant<int, v>;
I have few question about () operator. Please help me to get clear idea.
What is the use of () operator (() operator overloading).
In which situations it should use.
What are the practical example of () operator usage (in which situations that useful,convenient or suitable to use () operator ).
It's primarily used in function objects to simulate function calls.
#include <iostream>
struct Functor
{
void operator()() {
std::cout << "lol\n";
}
};
int main()
{
Functor f;
f(); // output: "lol"
}
Live demo
A contrived example, yes, but this gets more complex with constructor arguments and when, say, storing this functor for use in an algorithm. It's very common in the C++ standard library.
You don't have to use it in this way; another example is simulating multi-dimensional array access:
#include <vector>
template<typename T>
struct Matrix
{
Matrix(unsigned m, unsigned n)
: m(m), n(n), vs(m*n) {}
T& operator()(unsigned i, unsigned j)
{
return vs[i + m * j];
}
private:
unsigned m;
unsigned n;
std::vector<T> vs;
};
/**
* _~
* _~ )_)_~
* )_))_))_)
* _!__!__!_
* \______t/
* ~~~~~~~~~~~~~
*/
int main()
{
const unsigned int WIDTH = 3;
const unsigned int HEIGHT = 3;
Matrix<long> m(WIDTH, HEIGHT);
m(1,1) = 42;
}
This one is useful because operator[] may take only one parameter (though that parameter can be an initializer list, which is a workaround).
The () operator is used to make what is known as a function object aka "functor"
There are some very interesting things that having a function object allows one to do including passing a function object as a parameter.
The link I am posting below is a video from a class I was taking where the professor is talking about functors. I find it very helpful. (Note: the vid also talks about class templates)
Functors and Templates
In C++ how to tell compiler that Ogre::Vector3 IS_SAME_AS SomeOtherLIB::Vector3 ?
I feel that.. in languages like c++ which are not structural typed but there are cases when it makes sense.
Normally as game developer when working with 4+ libraries that provide sort or their own Vector3 implementation. The code is littered with ToOgre, ToThis, ToThat conversion function. Thats a lot of Float3 copying around which should not happen on first place.
Is in C++ or any other languages where we dont have to convert (copying) from one type to another which is essentially the samething. But any solution in C++ as most of the good gamedevs libs are for c/c++.
If you use templates you can define functions that take any type of argument as long as the necessary operations are defined on that type. Example:
class Foo { void quack() {} };
class Bar { void quack() {} };
class Baz {};
template<typename Duck>
void f(Duck d) {
d.quack();
}
int main() {
f(Foo()); // works
f(Bar()); // works
f(Baz()); // compile error because Baz does not have a quack method
return 0;
}
While it doesn't suit any situation, templates can give you "compile-time duck typing".
Lets say you have two vector types:
struct Vec3A {
float x, y, z;
};
struct Vec3B {
float p[3];
};
You can define function templates that hide the implementation how of to get the components:
template<class T> float get_x(const T&);
template<class T> float get_y(const T&);
template<class T> float get_z(const T&);
template<> float get_x<Vec3A>(const Vec3A& v) { return v.x; }
// ...
template<> float get_x<Vec3B>(const Vec3B& v) { return v.p[0]; }
// ...
With such helpers you can now write generic functions that work on both:
template<class T> float length(const T& t) {
return std::sqrt(std::pow(get_x(t), 2),
std::pow(get_y(t), 2),
std::pow(get_z(t), 2));
}
You can also continue by specializing utilities like length() for performance or other reasons, e.g. if a certain vector already has a member function providing you with the length:
template<> float length<Vec3C>(const Vec3C& v) {
return v.length();
}
If you are really sure in case of non-virtual structures, you can do a reinterpret_cast. However, it's better to:
do templated wrapper functions as shown by sepp2k
inherit from one of the vectors and add a conversion operator to the other vector
add a separate _cast function that does the conversion
Haxe is a highly portable language with completely optional structural subtyping:
typedef Vector3 = { x : double, y : double, z : double };
class FancyVector3 {
public var x : double, y : double, z : double;
function dot(Vector3 v) {
return x * v.x + y * v.y + z * v.z;
}
function length() {
return Math.sqrt(dot(this));
}
}
Not only is Vector3 an already usable structure, it also acts as a structural interface for other classes. Such typedef'd structs can specify function signatures as well as fields.
Haxe also has a CFFI for talking to C++ (although it still requires conversion methods), and bindings already exist for a few C++ game engines, as well as a variety of lower-level frameworks. Cross-platform engines written in pure Haxe are also being developed, targeting variously C++, Flash, and JS (both Canvas and WebGL).
This is probably not the solution you are looking for right now, but may become more interesting within a few years.