Ignore reference function argument - c++

I have function with this signature (I can not edit it):
void foo(int a,int b, int& c);
I want to call it but I do not care about the getting c. Currently I do this:
int temp;
foo(5,4,temp);
//temp never used again
My solution seems dumb. What is the standard way to ignore this argument.

There is none.
If your main concern is about polluting the current stack with a temp variable, a wrapper function like this should suffice:
void foo_wrapper(int a, int b)
{
int temp; foo(a, b, temp);
}

I would write an overload that turns the output argument into a normal return value. I really don't like output arguments and think that they should be avoided.
int foo(int a, int b) {
int tmp = 0;
foo(a,b, tmp);
return tmp;
}
In your program, you just this overload and either ignore the return value or use it.

This is an over engineered solution, so I don't actually recommend it as the first option in production code.
You can create a class to help you easily ignore these kinds of arguments:
template <class T>
struct RefIgnore
{
static inline T ignored_{};
constexpr operator T&() const
{
return ignored_;
}
};
template <class T>
constexpr RefIgnore<T> ref_ignore{};
void foo(int a,int b, int& c);
auto test()
{
foo(2, 3, ref_ignore<int>);
}

Instead of reference you can pass it as a pointer
void foo(int a,int b, int *c = NULL);
in calling place you can either have it as
foo(5, 6);
or if you want to pass the 3rd argument then you can have it as
int n = 3;
foo (1, 2, &n);

Related

How to avoid code duplication with function overloading

I have a pair of overloaded functions:
void func(const std::string& str, int a, char ch, double d) {
// piece of code A
sendMsg(str, a, ch, d);
// piece of code B
}
void func(int a, char ch, double d) {
// piece of code A
sendMsg(a, ch, d);
// piece of code B
}
piece of code A and piece of code B are exactly the same, the only difference is the parameter of sendMsg.
Is there some way to avoid the code duplication?
template may be a possibility:
template <typename ... Ts>
auto func(const Ts&... args)
-> decltype(sendMsg(args...), void()) // SFINAE to only allow correct arguments
{
// piece of code A
sendMsg(args...);
// piece of code B
}
but moving // piece of code A in its own function would probably be my choice.
You would have to do something like
void codeA() {
// ...
}
void codeB() {
// ...
}
void func(const std::string& str, int a, char ch, double d) {
codeA();
sendMsg(str, a, ch, d);
codeB();
}
void func(int a, char ch, double d) {
codeA();
sendMsg(a, ch, d);
codeB();
}
Another idea would be to give a default value to str:
void func(int a, char ch, double d, const std::string& str = "")
{
// piece of code A
if (str.empty()) sendMsg(a, ch, d);
else sendMsg(str, a, ch, d);
// piece of code B
}
Of course, use a functor:
template <typename F> void func2(F&& f) {
// piece of code A
f();
// piece of code B
}
Usage:
void func(int a, char ch, double d) {
func2([&](){ sendMsg(a, ch, d); });
}
A bit of explanation: Currently accepted answer is totally fine when you need to call the exactly same code with different parameters. But when you need to "inject" an arbitrary code (possibly a multiple pieces of arbitrary code) into another function, passing a temporary lambda is your best bet. Conceptually, what receiving function is seeing/getting is some abstract "callable" object (in fact, it can be anything with operator (), not just lambda) which it calls at due time. And since its a templated function, it will be compiled into zero-overhead code "as if" actual code was copy-pasted in there. The usage part is simply shows a c++ syntax to create a callable with arbitrary code in-place (I advise to read language references/tutorials on lambdas to understand the internals better).

Function overloading inside overloaded function

I am using C++14 (and pretty new to it). I have 3 overloaded functions func within which another overloaded function do_something gets called depending on its parent function (func).
int func(int a) {
bar(a);
foo();
}
int func(int a, float b) {
bar(a);
do_something(b);
foo();
}
int func(int a, float b, char c) {
bar(a);
do_something(b, c);
foo();
}
I see that the functionality within func is almost the same except which version of do_something gets called. Is there any way I can make this generic and combine all func's together?
To begin with, make func a template that accepts a parameter pack. The int a argument, the call to bar and the call to foo are always there, so that's simple. Let's add a placeholder for do_something for now.
template <class ...Args>
int func(int a, Args&&... other)
{
bar(a);
// somehow call do_something and do the right thing
foo();
return 0;
}
You want to instantiate and invoke the above template as before:
func(42);
func(42, 1.f);
func(42, 1.f, 'A');
Now let's tackle the call to do_something. If you simply add it in the middle of the new func template;
do_something(std::forward<Args>(other)...);
this refuses to compile for func(42), i.e., the case with only one argument. Hence, we need a special case for this. One way to achieve this in another level of indirection for do_something:
// No additional argument case, does nothing:
void do_something_wrapper() {}
// The other two cases
template <class ...Args>
void do_something_wrapper(Args&&... args)
{
do_something(std::forward<Args>(args)...);
}
And now, the placeholder from the func function template should be:
do_something_wrapper(std::forward<Args>(other)...);
The first step would be to use variadic-templates to take the part you want to forward to do_something:
template<class ... Args>
int func(int a, Args... args)
{
bar(a);
do_something(std::forward<Args>(args)...)
foo();
}
But now you have lost the argument types of func. So if this is a problem you will have to find a way to test them again.
Although I would probably go with the answer from generic_opto_guy myself, he's right to point out that you would lose the types in your interface. Depending on your situation, you might want to preserve this.
In that case, you can easily rework it to something akin to the following:
namespace details {
template<class ... Args>
int func_impl(int a, Args &&... args)
{
bar(a);
do_something(std::forward<Args>(args)...)
foo();
}
}
int func(int a) { return details::func_impl(a); }
int func(int a, float b) { return details::func_impl(a, b); }
int func(int a, float b, char c) { return details::func_impl(a, b, c); }
Note that the implementation has been adjusted to use perfect forwarding. While not required in this particular case, it is often useful in forwarding situations you might encounter in the future.
Again, unless you absolutely need to present a clear interface to client code, I would just go with the first implementation.
The other answers are good general purpose answers to the question as asked, but if you have a few "spare" values of c available, you could write something like:
int func(int a) {
func(a, 0.0,'\001');
}
int func(int a, float b, char c = '\002') {
bar(a);
switch (c) {
case '\001':
break; // func(a)
case '\002':
do_something(b): // func(a, b)
break;
default:
do_something(b, c); // func(a, b, c)
break;
}
foo();
}
Depending on the application, this may be simpler.
Is too late to play?
You tagged C++14 but, if you could use C++17, you could use if constexpr so
template <typename ... Ts>
int func (int a, Ts && ... ts)
{
bar(a);
if constexpr ( sizeof...(Ts) > 0u )
do_something(std::forward<Ts>(ts)...);
foo();
// and remember to return something of int
}
In C++14 you have to duplicate something somewhere.
Or you write two func()s
int func (int a)
{
bar(a);
foo();
// and remember to return something of int
}
template <typename ... Ts>
int func (int a, Ts && ... ts)
{
bar(a);
do_something(std::forward<Ts>(ts)...);
foo();
// and remember to return something of int
}
or you add a no-argument do_something()
void do_something ()
{ }
or, as suggested by lubgr, you call do_something() through a wrapper (creating a special no-argument wrapper).

Passing a single argument to a multi argument function

I have a variable let say int c in a given function. I want to pass it to the other class.let say it is
function(int a, int b, int c);
I want only to pass the third argument while ignore the first two.
i.e. : I just want to pass int c, as function (c) and it just pass it to the third argument. I don't want to pass it like function(0,0,c); .. Is there any possibility. Please advise.
Looks like you want to do function overloading. Something like this-
function(int a, int b, int c);
function(int c);
inside second function you can call first function with appropriate values for a and b
You can have default values for your function:
void function(int c, int a = 0, int b = 0);
or you can overload your function:
void function(int a, int b, int c) {
//implementation 1
}
void function(int c) {
function(0, 0, c);
}
You could in both cases use it like this:
function(c);
Note : when we use default values, in function definition the argument with default values must be the last in order for example :
void function(int a = 0, int b = 0, int c)
is not a valid format.
When you have the situation where function(c) is equivalent to function(0, 0, c), it sounds like a poor design. Normally, you can use default argument values for the parameters starting from the end. It would make sense if function(c) were equivalent to function(c, 0, 0).
You can accomplish that easily by declaring the function as:
void function(int c, int a = 0, int b = 0);
I realize that you can accomplish your goal by overloading function as:
void function(int c)
{
function(0, 0, c);
}
but it still appears to be a poor interface to me.
Imho already with three parameters it is worth to structure them
struct foo {
int a;
int b;
int c;
};
allowing to have a nicer function interface
void function(foo f);
How does this help? You can provide a default constructor and let the user set only those fields that are not default:
struct foo {
int a;
int b;
int c;
foo() : a(0),b(0),c(0) {}
};
foo f;
f.b = 12;
f.c = 32;
function(f);
Now any combination of default / non-defaults is possible.
One could argue that the struct isnt really necessary and the problem is just shifted to the constructor of foo or the need to correctly set the members, but I think this is a valid approach that was missing from the other answers. (btw I am not claiming that my example here demonstrates best pratice, but the details would matter on the exact use case)

Pointer-to-member as template argument

I use Visual C++ 2012. I want to parameterize a template function with a pointer to another function. It all works nicely outside of a class:
int add(int a, int b) {
return a + b;
}
typedef int (*func)(int a, int b);
template<func F> int do_it(int a, int b) {
return F(a, b);
}
int foo(int a, int b) {
return do_it<add>(a, b);
}
Visual C++ 2012 compiles and optimizes that perfectly.
Now, I put it inside a class and adjust it for pointer-to-member:
struct S {
int add(int a, int b) {
return a + b;
}
typedef int (S::*func)(int a, int b);
template<func F> int do_it(int a, int b) {
return F(a, b); // <-- here be error!
}
int foo(int a, int b) {
return do_it<&S::add>(a, b);
}
};
S s;
int bar(int a, int b) {
return s.foo(a, b);
}
But that gives me a compiler-error:
Microsoft (R) C/C++ Optimizing Compiler Version 17.00.51106.1 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
x2.cpp
x2.cpp(7) : error C2064: term does not evaluate to a function taking 2 arguments
x2.cpp(10) : see reference to function template instantiation 'int S::do_it<int S::add(int,int)>(int,int)' being compiled
Any idea why and how to fix it?
The syntax for pointers to members still apply. You should write :
typedef int (S::*func)(int a, int b);
template<func F> int do_it(int a, int b) {
return (this->*F)(a, b);
}
Using a pointer to member always require associating an object with it - here, it makes sense you would call your pointer on this.
Member-function pointers must be called on an object; unlike a normal member function call, this must be specified explicitly:
(this->*F)(a,b);
Although, if the function doesn't need to access this, perhaps it should be static (or a non-member), specified by a normal function pointer.
It looks like you just need to call the member function pointer on an object:
template<func F> int do_it(int a, int b) {
return (this->*F)(a, b);
}
Pointers to members always need to be called on an object, unlike free and static member functions, which is why you need the above syntax.
You need to provide the object when calling a pointer-to-meber function:
(this->*F)(a, b);
One point further: write your "do_it" more generally as
template<class F> int do_it(F f, int a, int b) {
return f(a, b); }
Now, you can pass it any function of two integers:
int mul(int a, int b) { return a*b ; }
S s;
s.do_it(mul,2,3);
When you intend to use it inside your class with a member function, just bind it with this. Using boost::bind,
int foo(int a, int b) {
return do_it( boost::bind(&S::add,this,_1,_2),a,b) ;

Can I set a default argument from a previous argument?

Is it possible to use previous arguments in a functions parameter list as the default value for later arguments in the parameter list? For instance,
void f( int a, int b = a, int c = b );
If this is possible, are there any rules of use?
The answer is no, you can't. You could get the behaviour you want using overloads:
void f(int a, int b, int c);
inline void f(int a, int b) { f(a,b,b); }
inline void f(int a) { f(a,a,a); }
As for the last question, C doesn't allow default parameters at all.
No, that is not legal C++. This is specified in section 8.3.6/9 of the C++ Standard:
Default arguments are evaluated each
time the function is called. The
order of evaluation of function arguments
is unspecified. Consequently,
parameters of a function shall not be
used in default argument expressions,
even if they are not evaluated.
and:
int f(int a, int b = a); // error:
parameter a used as default argument
And C89 at least does not support default parameter values.
As a potential workaround, you could do:
const int defaultValue = -999; // or something similar
void f( int a, int b = defaultValue, int c = defaultValue )
{
if (b == defaultValue) { b = a; }
if (c == defaultValue) { c = b; }
//...
}
This is not possible
No, you cannot do that.You will surely get an error "Local variable may not appear in this context".
Your first idea might be to do something like this :
void something(int a, int b=-1, int c=-1){
if(b == -1)
b = a;
if(c == -1)
c = b;
}
I used -1 because this function only works with positive values. But what if someone uses my class and makes a mistake which ends up sending -1 to the method? It would still compile and execute, but the result would be unpredictable for the user. So the smart thing to do would be to remove any default argument and instead make a bunch of methods with the same name like this:
void something(int a, int b, int c){
/* Do something with a, b and c */
}
void something(int a){
something(a, a, a);
}
void something(int a, int b){
something(a, b, b);
}
It doesn't really take much longer to code, and if someone uses it in a programming interface with auto-complete features, it will show the 3 possible prototypes.
I do not think you can do that as that is an illegal syntax. But however, consult the C99 standard in pdf format (n1136.pdf).
However, you may get around this by using static as in declaring the variables static and using them within the function f
static int global_a;
/* In some other spot where you are calling f(), do this beforehand */
/* global_a = 4; f(); */
void f(void){
int a = global_a;
b = c = a;
/* ..... */
}
Kudos to Michael Burr for pointing out my error! :)
It sounds like you need to rethink your code and change it around for something like that.