I have questions on where to even start on this problem.
The problem requires the following.
// We want to create a function that will add numbers together,
// when called in succession.
add(1)(2); // == 3
I have never seen functions be used in such a way, and I am currently at a loss of where to start. Furthermore, I tried to do some research on parameter chaining, but this is all I could find.
https://levelup.gitconnected.com/how-to-implement-method-chaining-in-c-3ec9f255972a
If you guys have any questions, I can edit my code or question. Any help is appreciated.
.... way and I am currently at a loss of where to start?
One way, is to start with an anonymous (unnamed) functor✱, which has operator(), that returns the reference to the this, as follows:
struct { // unnamed struct
int result{ 0 };
auto& operator()(const int val) noexcept
{
result += val;
return *this; // return the instance itself
}
// conversion operator, for converting struct to an int
operator int() { return result; }
} add; // instance of the unnamed struct
int main()
{
std::cout << add(1)(2); // prints: 3
}
See a live demo
✱Read more about the unnamed structs, functors and conversion operator here:
What are "anonymous structs" / "unnamed structs"?
What are C++ functors and their uses?
How do conversion operators work in C++?
The trick is to overload operator() and use a proxy object.
struct LhsAddProxy
{
int lhs_;
int operator()(int rhs) const { return lhs_ + rhs; }
};
LhsAddProxy add(int lhs) { return {lhs}; }
Related
In many of my unit tests I need to compare the contents of simple structs having only data members:
struct Object {
int start;
int stop;
std::string message;
}
Now, if I want to write something like:
CHECK(object1==object2);
I always have to implement:
bool operator==(const Object& lhs, const Object& rhs) {
return lhs.start==rhs.start && lhs.stop==rhs.stop && lhs.message=rhs.message;
}
Writing all these comparison functions becomes tedious, but is also prone to errors. Just imagine, what will happen if I add a new data member to Object, but the comparison operator will not be updated.
Then I remembered my knowledge in Haskell and the magic deriving(Eq) directive, which just generates a sane comparison function for free.
How, could I derive something similar in C++?
Happily, I figured out that C++17 comes with a generic operator== and that every struct should be easily convertible to an std::tuple by the virtue of std::make_tuple.
So I boldly tried the following:
#include <tuple>
#include <iostream>
#include <tuple>
template<typename T>
bool operator==(const T& lhs, const T& rhs)
{
auto leftTuple = std::make_tuple(lhs);
auto rightTuple = std::make_tuple(rhs);
return leftTuple==rightTuple;
}
struct Object
{
std::string s;
int i;
double d;
};
int main(int arg, char** args)
{
std::cout << (Object{ "H",1,2. } == Object{ "H",1,2. }) << std::endl;
std::cout << (Object{ "A",2,3. } == Object{ "H",1,2. }) << std::endl;
return EXIT_SUCCESS;
}
But, unfortunately it just doesn't compile and I really don't know why. Clang tells me:
main.cpp:11:18: error: use of overloaded operator '==' is ambiguous (with operand types
'std::tuple<Object>' and 'std::tuple<Object>')
return leftTuple==rightTuple;
Can I possibly fix this compile error to get my desired behavior?
No, since comparing tuples reverts to comparing the elements of the tuple, so leftTuple == rightTuple tries to compare two Objects which is not possible.
that every struct should be easily convertible to an std::tuple by the virtue of std::make_tuple
No, you'll just get a tuple with one element, the struct.
The trick is to use std::tie:
std::tie(lhs.mem1, lhs.mem2) == std::tie(rhs.mem1, rhs.mem2)
but that has the same problem as your original solution. Unfortunately C++17 doesn't have any facility to avoid this problemyou could write a macro :). But in C++20 you will be able to do:
struct Object
{
std::string s;
int i;
double d;
bool operator==(const Object &) const = default;
};
which will generate the correct comparison operators for Object.
I know that a return value is not enough to override a function (and I read different threads about it on stackoverflow), but is there a way to overload the subscript operator of a class, just to return the value (I can't changed to to return by reference-type of function)
It has to look like or at least work like:
What's the best approach to solve this problem (It has to be a operator)?
Update:
The Problem is, that's not allowed to just overload a member or operator just with the return type.
struct A {int a; int b; double c;};
struct B {int a; int b; array<double,2> c;};
class Whatever
{
public:
A operator [](unsigned int ) const; //it's just reading the element
B operator [](unsigned int ) const;
}
A operator [](unsigned int Input){
//...
}
B operator [](unsigned int Input){
//...
}
Assuming you know what kind of type you are going to access, you can return a proxy which converts to either type and, probably, does the access upon conversion. Since you want to access a const object that should be fairly straight forward. Things get a bit more messy when trying to do the same for an updating interface:
class Whatever;
class Proxy {
Whatever const* object;
int index;
public:
Proxy(Whatever const* object, int index)
: object(object)
, index(index) {
}
operator A() const { return this->object->asA(this->index); }
operator B() const { return this->object->asB(this->index); }
};
class Whatever {
// ...
public:
Proxy operator[](int index) { return Proxy(this, index); }
A asA(index) { ... }
B asB(index) { ... }
};
The main constraint is that you can't access members of A and B directly: you need to convert to an A or a B first. If the two types are actually known, you can created a Proxy which forwards the respective member function appropriately. Of course, if there are commonly named member functions or data members you'll need to explicitly convert first.
Could someone explain me what is going on in this example here?
They declare the following:
bool fncomp (int lhs, int rhs) {return lhs<rhs;}
And then use as:
bool(*fn_pt)(int,int) = fncomp;
std::set<int,bool(*)(int,int)> sixth (fn_pt)
While the example for the sort method in algorithm library here
can do like this:
bool myfunction (int i,int j) { return (i<j); }
std::sort (myvector.begin()+4, myvector.end(), myfunction);
I also didn't understand the following:
struct classcomp {
bool operator() (const int& lhs, const int& rhs) const
{return lhs<rhs;}
};
this keyword operator (not being followed by an operator as in a op. overload)... what is the meaning of it? Any operator applied there will have that behavior? And this const modifier... what is the effect caused by it?
I was trying to make a set of C-style string as follows:
typedef struct
{
char grid[7];
} wrap;
bool compare(wrap w1, wrap w2)
{
return strcmp(w1.grid, w2.grid) == -1;
}
set <wrap, compare> myset;
I thought I could create a set defining my sorting function in a similar as when I call sort from algorithm library... once it didn't compile I went to the documentation and saw this syntax that got me confused... Do I need to declare a pointer to a function as in the first example i pasted here?
struct classcomp {
bool operator() (const int& lhs, const int& rhs) const
{return lhs<rhs;}
};
Defines a functor by overloading the function call operator. To use a function you can do:
int main() {
std::set <wrap, bool (*)(wrap,wrap)> myset(compare);
return 0;
}
Another alternative is to define the operator as a part of the wrap class:
struct wrap {
char grid[7];
bool operator<(const wrap& rhs) const {
return strcmp(this->grid, rhs.grid) == -1;
}
};
int main() {
wrap a;
std::set <wrap> myset;
myset.insert(a);
return 0;
}
You're almost there... here's a "fixed" version of your code (see it run here at ideone.com):
#include <iostream>
#include <set>
#include <cstring>
using namespace std;
typedef struct
{
char grid[7];
} wrap;
bool compare(wrap w1, wrap w2) // more efficient: ...(const wrap& e1, const wrap# w2)
{
return strcmp(w1.grid, w2.grid) < 0;
}
set <wrap, bool(*)(wrap, wrap)> myset(compare);
int main() {
wrap w1 { "abcdef" };
wrap w2 { "ABCDEF" };
myset.insert(w1);
myset.insert(w2);
std::cout << myset.begin()->grid[0] << '\n';
}
"explain [to] me what is going on in this example"
Well, the crucial line is...
std::set<wrap, bool(*)(wrap, wrap)> myset(compare);
...which uses the second template parameter to specify the type of function that will perform comparisons, then uses the constructor argument to specify the function. The set object will store a pointer to the function, and invoke it when it needs to compare elements.
"the example for the sort method in algorithm library..."
std::sort in algorithm is great for e.g. vectors, which aren't automatically sorted as elements are inserted but can be sorted at any time. std::set though needs to maintain sorted order constantly, as the logic for inserting new elements, finding and erasing existing ones etc. all assumes the existing elements are always sorted. Consequently, you can't apply std::sort() to an existing std::set.
"this keyword operator (not being followed by an operator as in a op. overload)... what is the meaning of it? Any operator applied there will have that behavior? And this const modifier... what is the effect caused by it?
operator()(...) can be invoked on the object using the same notation used to call a function, e.g.:
classcomp my_classcomp;
if (my_classcomp(my_int1, my_int_2))
std::cout << "<\n";
As you can see, my_classcomp is "called" as if it were a function. The const modifier means that the code above works even if my_classcomp is defined as a const classcomp, because the comparison function does not need to modify any member variables of the classcomp object (if there were any data members).
You almost answered your question:
bool compare(wrap w1, wrap w2)
{
return strcmp(w1.grid, w2.grid) == -1;
}
struct wrap_comparer
{
bool operator()(const wrap& _Left, const wrap& _Right) const
{
return strcmp(_Left.grid, _Right.grid) == -1;
}
};
// declares pointer to function
bool(*fn_pt)(wrap,wrap) = compare;
// uses constructor with function pointer argument
std::set<wrap,bool(*)(wrap,wrap)> new_set(fn_pt);
// uses the function directly
std::set<wrap,bool(*)(wrap,wrap)> new_set2(compare);
// uses comparer
std::set<wrap, wrap_comparer> new_set3;
std::sort can use either a function pointer or a function object (http://www.cplusplus.com/reference/algorithm/sort/), as well as std::set constructor.
const modifier after function signature means that function can't modify object state and so can be called on a const object.
I have a question related to operator overloading, and it is easy to define a class as well as its operator overloading function as the following codes illustrate:
typedef std::vector<std::vector<int> > ARRAY;
class ABC
{
public:
ABC():a(0)
{
};
int a;
ABC& operator = (int value)
{
a = value;
return *this;
}
ABC(int value)
{
a = value;
}
};
void obtain_priority_array(const std::vector<double> &weighting, const ABC &priority_array=NULL)
{
}
int main()
{
vector<double> weighting;
weighting.push_back(0.8);
weighting.push_back(0.9);
weighting.push_back(0.6);
weighting.push_back(0.3);
weighting.push_back(0.5);
ABC test;
obtain_priority_array(weighting, test);
return 0;
}
In the above example, class ABC redefined operator = so that the function void obtain_priority_array(const std::vector<double> &weighting, const ABC &priority_array=NULL) can have a default argument const ABC &priority_array=NULL. My question is if the last parameter in the function comes from STL, for example, const std::vector<int> &priority_array=NULL, how can we redefine operator =. Thanks!
EDIT:
void obtain_priority_array(const std::vector &weighting, const std::vector<int> &sample=NULL) failed!
Your misconceptions start with the proposal to add operator= to allow for a default argument of that type. In your example, it is not operator= being called, but ABC(int).
The reason your code isn't being accepted when using std::vector is that NULL translates to 0 (at least it does almost all of the time you'll see it), and the only constructor of std::vector that can take 0, the one taking a count of how many items, is marked explicit.
To fix the immediate problem, the syntax could be changed to:
const std::vector<int> &priority_array = std::vector<int>(0)
However, this introduces different semantics. By your use of NULL, it looks like you were expecting it to represent no vector. This version will provide an empty vector for use if none is given. It will not be no vector at all. If you want that distinction, you should use boost's optional library, or a simple pointer, as references are not the right tool.
References cannot be NULL, your problem has nothing to do with operator overloading. If you want to be able to handle NULL as the default value, switch the parameter type from reference to pointer.
void obtain_priority_array( const std::vector<double>& weighting,
const ABC *priority_array = NULL)
{
if( priority_array == NULL ) {
// blah
} else {
// more blah
}
}
Another option is to use something like Boost.Optional to represent the optional parameter.
typedef boost::optional<ABC> maybe_ABC;
void obtain_priority_array( const std::vector<double>& weighting,
const maybe_ABC& priority_array = maybe_ABC() )
{
if( !priority_array ) {
// blah
} else {
// more blah
}
}
When you use = to create a reference, you're not calling operator= at all. You're initializing the reference.
Instead of using NULL you can create a static instance of the class to represent a null value.
static const ABC ABC_NULL;
void obtain_priority_array(const std::vector<double> &weighting, const ABC &priority_array=ABC_NULL)
{
if (&priority_array == &ABC_NULL) // the default was used
Of course it would be easier to just use a pointer instead of a reference.
the question may look silly ,but i want to ask..
Is there any way we can declare a method in a class with same signature but different return type (like int fun(int) and float fun(int) ) and during the object creation can we dynamically decide which function to be executed! i have got the compilation error...is there any other way to achieve this logic may be using templates...
You can always take the return value as a template.
template<typename T> T fun(int);
template<> float fun<float>(int);
template<> int fun<int>(int);
Can you decide dynamically at run-time which to call? No.
#DeadMG proposed the template based solution, however you can simply "tweak" the signature (which is, arguably, what the template argument does).
The idea is simply to add a dummy argument:
struct Foo
{
float fun(float); // no name, it's a dummy
int fun(int); // no name, it's a dummy
};
Then for execution:
int main() {
Foo foo;
std::cout << foo.fun(int()) << ", " << foo.fun(float());
}
This can be used exactly as the template solution (ie invoked from a template method), but is much easier to pull:
less wordy
function template specialization should be defined outside the class (although VC++ will accept inline definition in the class)
I prefer to avoid function template specialization, in general, as with specialization on arguments, the rules for selecting the right overload/specialization are tricky.
You can (but shouldn't*) use a proxy class that overloads the conversion operators.
Long example with actual usecase *
Let me take my example from Dot & Cross Product Notation:
[...]
There is also the possibility of having operator* for both dot-product and cross-product.
Assume a basic vector-type (just for demonstration):
struct Vector {
float x,y,z;
Vector() {}
Vector (float x, float y, float z) : x(x), y(y), z(z) {}
};
We observe that the dot-product is a scalar, the cross-product is a vector. In C++, we may overload conversion operators:
struct VecMulRet {
public:
operator Vector () const {
return Vector (
lhs.y*rhs.z - lhs.z*rhs.y,
lhs.z*rhs.x - lhs.x*rhs.z,
lhs.x*rhs.y - lhs.y*rhs.x
);
}
operator float () const {
return lhs.x*rhs.x + lhs.y*rhs.y + lhs.z*rhs.z;
}
private:
// make construction private and only allow operator* to create an instance
Vector const lhs, rhs;
VecMulRet (Vector const &lhs, Vector const &rhs)
: lhs(lhs), rhs(rhs)
{}
friend VecMulRet operator * (Vector const &lhs, Vector const &rhs);
};
Only operator* is allowed to use struct VecMulRet, copying of VecMulRet is forbidden (paranoia first).
Operator* is now defined as follows:
VecMulRet operator * (Vector const &lhs, Vector const &rhs) {
return VecMulRet (lhs, rhs);
}
Et voila, we can write:
int main () {
Vector a,b;
float dot = a*b;
Vector cross = a*b;
}
Btw, this is blessed by the Holy Standard as established in 1999.
If you read further in that thread, you'll find a benchmark that confirms that this comes at no performance penalty.
Short example for demonstration *
If that was too much to grasp, a more constructed example:
struct my_multi_ret {
operator unsigned int() const { return 0xdeadbeef; }
operator float() const { return 42.f; }
};
my_multi_ret multi () {
return my_multi_ret();
}
#include <iostream>
#include <iomanip>
int main () {
unsigned int i = multi();
float f = multi();
std::cout << std::hex << i << ", " << f << std::endl;
}
* You can, but shouldn't, because it does not conform to the principle of least surprise as it is not common practice. Still, it is funny.