C++ overloaded function calling version of itself with more arguments - c++

I am using function overload to have a general version of a behaviour and a more usual one. The usual function just picks a default value for the second argument that actually depends on the first, and the compiler is giving me an error because it does not even recognize the existence of the second function. I also tried to do it with default values, but because the default depends on the first argument, the compiler does not seem to accept it.
So, here are simplified examples just for illustration.
Function overloading case:
#include <stdio.h>
struct pair {
int x;
int y;
};
int func(pair a){
return func(a, a.y);
}
int func(pair a, int b) {
return a.x*b;
}
int main() {
pair z;
z.x = 2;
z.y = 4;
printf("%d\n", func(z));
printf("%d\n", func(z,12));
}
This gives me the error:
a.c: In function ‘int func(pair)’:
a.c:9:21: error: too many arguments to function ‘int func(pair)’
a.c:8:5: note: declared here"
Example with default values:
#include <stdio.h>
struct pair {
int x;
int y;
};
int func(pair a, int b = a.y) {
return a.x*b;
}
int main() {
pair z;
z.x = 2;
z.y = 4;
printf("%d\n", func(z));
printf("%d\n", func(z,12));
}
Gives me the following error: "local variable a may not appear in this context"
So, is there any way in C++ to emulate this behaviour? I never had this problem in other languages, like Java or even in ASP.
Thank you all.

In C and C++, before the function call, that function should be declared or defined. Here you are making a call to return func(a, a.y); but the function func(pair, int) has not yet been declared or defined.
You need to change the definitions of the two functions, or just declare the functions in the beginning of your code. As other answers have explained the first approach, here is the snippet with second approach.
#include <stdio.h>
//Function Declaration
int func(pair);
int func(pair, int);
struct pair {
int x;
int y;
};
int func(pair a){
return func(a, a.y);
}
int func(pair a, int b) {
return a.x*b;
}
int main() {
pair z;
z.x = 2;
z.y = 4;
printf("%d\n", func(z));
printf("%d\n", func(z,12));
}

Switch the order of the definitions of func(), such that the 2 argument version is defined before the one argument version. The compiler doesn't know the 2 argument version exists until it encounters the definition, so you can't call it until you've told the compiler it exists.

You have to change the order of the definitions:
int func(pair a, int b) {
return a.x*b;
}
int func(pair a){
return func(a, a.y);
}
LIVE DEMO
This is happening because in int func(pair a) you are calling int func(pair a, int b) which is not visible. Changing the order of definitions like above solves this problem.

Related

Call a class's function template with function pointers as parameters

I'd want to use a function pointer in my template argument list. I do miss something of B even I am writing int in full main of both A and B. I have a class X.h like so, don't know which one it is now causing the error.
struct X
{
int fun(int a)
{
return a;
}
template<typename A, typename B>
A func(int x, B(*f)(int))
{
A i = 10;
return i + f(x);
}
};
and I like to use it in main.cpp
int main()
{
X d;
std::cout << d.func<int, int>(10, &X::fun) << "\n";
return 0;
}
The error is No instance of func matches the argument list...
The problem is that the argument &X::fun is of type int (X::*)(int) while the parameter f is of type int(*)(int) (when B = int) and there is no implicit conversion from the former to the latter and hence the error.
To solve this you can change the parameter f to be of type B(X::*)(int) as shown below. Note that the syntax for making a call using member function pointer is different for making a call to a free function.
With C++17, we can use std::invoke.
struct X
{
int fun(int a)
{
return a;
}
template<typename A, typename B>
//------------------vvvv-------------->added this X:: here
A func(int x, B(X::*f)(int))
{
A i = 10;
//-----------------vvvvvvvvvv-------->this is the syntax to call using member function pointer
return i + (this->*f)(x);
//return std::invoke(f, this, x); //use std::invoke with C++17
}
};
int main()
{
X d;
std::cout << d.func<int, int>(10, &X::fun) << "\n"; //works now
return 0;
}
Working demo

Alias Declarations in C++

I have come across this code snippet and have no idea what it means:
#include <iostream>
int main(){
using test = int(int a, int b);
return 0;
}
I can guess test can be used instead of int(int a, int b), but what does int(int a, int b) even mean? is it a function? How can it be used?
int(int a, int b) is a function declaration that has two parameters of the type int and the return type also int.
You can use this alias declaration for example as a member function declarations of a class or using it in a parameter declaration.
It's an alias for a function signature.
A more complete usage is to declare a pointer or reference to a function
int foo(int, int);
int main()
{
using test = int(int a, int b); // identifiers a and b are optional
test *fp = &foo;
test *fp2 = foo; // since the name of function is implicitly converted to a pointer
test &fr = foo;
test foo; // another declaration of foo, local to the function
fp(1,2); // will call foo(1,2)
fp2(3,4); // will call foo(3,4)
fr(5,6); // will call foo(5,6)
foo(7,8);
}
Just to give another use option of this line, with lambda expressions:
int main() {
using test = int(int, int);
test le = [](int a, int b) -> int {
return a + b;
}
return 0;
}
One point that you have to keep in mind about this use of test, there are probably more efficient ways to declare a function signature, like auto in lambda expressions case, template in case of passing function as argument to another function, etc.
This way came all the way from pure C programming, with the using twist. I won't recommend of choosing this way, but for general understanding it is always good to know more than the correct ways.

C++ member function with auto and default arguments

I am trying to implement a member function in a C++ class which has an auto argument (a lambda) and an int argument with a default value. Something like this:
class Base {
public:
int add_one(auto fobj, int b=3);
};
int Base::add_one(auto add_fcn, int b) {
return add_fcn(1, b);
}
However, a simple test like this fails to compile:
#include <iostream>
class Base {
public:
int add_one(auto fobj, int b=3);
};
int Base::add_one(auto add_fcn, int b) {
return add_fcn(1, b);
}
int main() {
int ans;
auto add_fcn = [](int a, int b) -> int {return a + b;};
Base obj;
ans = obj.add_one(add_fcn);
std::cout << ans << "\n";
return 0;
}
The error the compiler (MinGW 7.2.0, flags: -std=c++14) gives me is the following:
error: call to 'int Base::add_one(auto:2, int) [with auto:1 = main()::<lambda(int, int)>]' uses the default argument for parameter 2, which is not yet defined
I sincerely do not understand the error. Can someone please explain me the reason of this error and how it can be fixed? Thank you in advance.
auto parameters is a gcc extension. It means that it is not a standard compliant way to solve the problem.
I am not sure what is the exact reason for the error above, but you might achieve the same effect with template member function which works well:
class Base {
public:
template<typename F>
int add_one(F fobj, int b = 3);
};
template<typename F>
int Base::add_one(F add_fcn, int b) {
return add_fcn(1, b);
}
Wandbox example
Another possible way is to use std::function (which implies some performance overhead though):
class Base {
public:
int add_one(std::function<int(int, int)> fobj, int b = 3);
};
int Base::add_one(std::function<int(int, int)> add_fcn, int b) {
return add_fcn(1, b);
}
Wandbox example
Finally, you could make use of pointers to functions, but it is too C way...
If you'd like to expand your knowledge on passing functions to functions, this article by Vittorio Romeo gives an excellent explanation + some benchmarks.

Getting member variables values set and then passed to a function c++

Probably a dumb question, I want to be able to use the passed in A & B values through the default constructor and use them in my functions like get(), but every time i do it gives the value of 0, how do i set the values of A & B and then be able to use them in my other functions. I know i could just pass the value into the get function from the main but i dont want to do it that way.
I have this in the .h,
class example
{
private:
int A, B;
public:
example();
example(int, int);
int get(int, int);
};
then in the .cpp
example::example()
{
cout << hello;
}
example::example(int x, int y)
{
A = x;
B = y;
}
int example::get(int c, int d)
{
int k = c + d / A;
return k;
}
And in the main()
int c = 10;
int d = 12;
int x = 2;
int y = 1;
example obj1(x, y);
example obj2;
int k = obj2.get(c, d);
cout << k;
Im thinking i should see an answer of 10 + 12 / 2 however its 10 + 12 / 0, not sure where i am going wrong if anyone could help thanks!
example(x, y);
does not do anything. It creates a temporary object that goes immediately out of scope. Then
example obj1;
should not compile, as you don't have a default constructor. If it compiles it means that you have provided a default constructor, which is invoked (and which probably doesn't do any initialization). However in your case you want to invoke the constructor example::example(int, int). The correct way of doing it is to define
example obj1(x, y);

Why is this allowed?

So I know it is disallowed to have functions with the same parameters and names:
int a(int b) {
return b;
}
int a(int b) {
return b;
}
int main() {
int c = a(4);
}
This above won't compile. But then I got thinking, what if I passed one by reference, and one by value?
int a(int b) {
return b;
}
int a(int& b) {
return b;
}
int main() {
int c = a(4);
}
The above does compile, I guess because you can't pass 4 to by reference, so it assumes you want the first a, which means the compiler can distinguish which function you want to call. If I then change main to this:
int main() {
int c = a(4);
a(c);
}
It will fail to compile, I assume because c can be passed to either function, so the compiler doesn't know which function to call.
But what about... THIS?
int a(const int& b) {
return b;
}
int a(int& b) {
return b;
}
int main() {
int c = a(4);
a(c);
}
This does compile. Why? I expected it to not, because c can be passed to both the first and second a. Is there some misconception I have?
My question specifically is, how come this (code below) does not compile, and the final one does?
int a(int b) {
return b;
}
int a(int& b) {
return b;
}
int main() {
int c = a(4);
a(c);
}
If I was the compiler, and I could choose which function to call based how close the parameters matched, for the call a(c), I could choose from both the first and second. Is there any reason that the first or second a cannot be chosen from in this example?
The process of choosing the correct function to use from a function call is called Overload Resolution. When a function is called, the compiler searches for all functions with that name (overloads) and compiles them into an overload set. Simply put, a best match is chosen by picking the functions that require the least conversions as possible from their parameters.
These are the two functions compiler chooses from a(c):
int a(const int& b);
int a( int& b);
The second overload is chosen because the first overload requires a const-qualification. The variable with which you called the function with, c, is non-const, so it is a perfect match for the second overload and can be bound to the non-const reference.
int a(const int& b) {
return b;
}
int a(int& b) {
return b;
}
int main() {
int c = a(4);
a(c);
}
When you call it with a(4) 4 is a literal and only your version taking a const reference can bind it, so that's the one being called.
Now when you call a(c) you got c as a non-const int it will therefore prefer the function taking a non-const reference.