Too many arguments, too few arguments in function pointer - c++

I'm trying to learn c++ from the basics, and I was playing around with function pointers. Considering this code:
#include <iostream>
#include <string>
#include <vector>
bool print(std::string);
bool print(std::string a)
{
std::cout << a << std::endl;
return true;
}
bool call_user_function(bool(std::string), std::vector<std::string>);
bool call_user_function(bool(*p)(std::string), std::vector<std::string> args) {
if (args.size() == 0)
return (*p)(); (*)
else if (args.size() == 1)
return (*p)(args[0]);
else if (args.size() == 2)
return (*p)(args[0], args[1]); (**)
}
int main(int argc, char** argv)
{
std::vector<std::string> a;
a[0] = "test";
call_user_function(print, a);
// ok
return 0;
}
It gives me:
main.cpp:28 (*): error: too few arguments to function
main.cpp:32 (**): error: too many arguments to function
What am I doing wrong?

p is of type bool(*)(std::string). This means it is a pointer to a function that has a single parameter of type std::string and returns a bool.
p can point to print, because the type of print matches: it is a function that has a single parameter of type std::string and returns a bool.
Your first erroneous expression, (*p)(), attempts to call p with no arguments. Your second erroneous expression, (*p)(args[0], args[1]) attempts to call p with two arguments.
The number of arguments must match the number of parameters, so both of these are ill-formed, just like an attempt to call print directly with no arguments or with two arguments would result in a compilation error.

#JamesMcNellis has already addressed the problem with the code.
To make something like this work, you probably want to do something like:
bool call_user_function(bool(*p)(std::string), std::vector<std::string> args) {
bool ret = true;
for (int i=0; i<args.size(); i++)
ret &= p(args[i]);
return ret;
}
...or, you could use std::for_each (and since you're not using it anyway, I'll ignore the return value for the moment):
// avoid copying vector by passing reference to const vector.
void call_user_function(bool (*p)(std::string), std::vector<std::string> const &args) {
std::for_each(args.begin(), args.end(), p);
}
...but, since you're just printing out the contents of the vector, what you should probably use is something more like this:
std::copy(a.begin(), a.end(),
std::ostream_iterator<std::string>(std::cout, "\n"));
Also note that your a[0] = "test"; is invalid. You want a.push_back("test"); instead.

print has no overload for a call with no arguments.
print also doesn't have an overload for two std::string arguments.

Related

remove a pair from a list of pairs c++

I'm doing this all in classes, I've a simple question, I've a private list of pairs:
std::list<std::pair<std::string, size_t>> pokemons_;
to which I've passed certain values as:
{("Pikachu", 25),
("Raticate", 20),
("Raticate", 20),
("Bulbasaur", 1),
("Pikachu", 25),
("Diglett", 50)};
Now I want to remove a pair by calling a public remove function of my class.
bool PokemonCollection::Remove(const std::string& name, size_t id){};
what I don't understand is how to compare the string and id value while calling the remove function:
collection.remove("Raticate", 20);
"collection Is an object of my class"
what I've implemented till now by the help of other forums and reading internet and cpp reference is:
bool PokemonCollection::Remove(const std::string& name, size_t id){
bool found;
string x;
size_t y;
for (auto currentPair : pokemons_){
pair<string, size_t> currentpair = currentPair;
x=currentpair.first;
y=currentpair.second;
pokemons_.erase(pokemons_.begin()+i)
for (int i=0; i<pokemons_.size(); i++){
if (pokemons_[i].first == x && pokemons_[i].second == y){
// pokemons_.erase(pokemons_.begin() +i);
cout<<"FOUND!!!!!!!!!!!!!!!";
found = true;
return true;
}else{
found = false;
}
}
}
return found;
}
but this remove function of mine gives some errors I don't really understand.
also it gives so much errors on the commented line where I used erase function. I just need some help to compare the string and id and remove that pair from original private list of my class.
MY FUNCTION
```bool PokemonCollection::Remove(const std::string& name, size_t id){
bool found;
//string x;
//size_t y;
pokemons_.remove_if([&](std::pair<std::string, size_t>& p){return found = true and p.first==name and p.second==id;});
if(found==true){
return true;
}else{
found = false;
}
return found;
}```
There is a very simple solution to your problem.
The std::listhas a function remove_if, which will do everything for you. See here.
Please see the below code as an example:
#include <iostream>
#include <string>
#include <utility>
#include <list>
std::list<std::pair<std::string, size_t>> poke
{{"Pikachu", 25},
{"Raticate", 20},
{"Raticate", 20},
{"Bulbasaur", 1},
{"Pikachu", 25},
{"Diglett", 50}};
void remove(const std::string& s, size_t i) {
poke.remove_if([&](std::pair<std::string, size_t>& p){return p.first== s and p.second==i;});
}
int main() {
remove("Raticate", 20);
for (const auto& [s,i] : poke)
std::cout << s << '\t' << i <<'\n';
}
Some more information:
As you can read in the remove_if documentation of the std::list, it needed to be called as following:
void remove_if( UnaryPredicate p );
The problem for you maybe the "UnaryPredicate". We can read:
unary predicate which returns ​true if the element should be removed.
and, we can read further:
The expression p(v) must be convertible to bool for every argument v of type (possibly const) T, regardless of value category, and must not modify v. Thus, a parameter type of T&is not allowed, nor is T unless for T a move is equivalent to a copy (since C++11). ​
But this will also not help you very much. Basically a predicate is, extremely simplified, a function (object).
So, remove_if will iterate over all elements in the std::list and call this "function". If this "function" returns true, then then the associated list-element will be removed.
The C++ standard defines Predicate as follows (25/7):
The Predicate parameter is used whenever an algorithm expects a function object that when applied to the result of dereferencing the corresponding iterator returns a value testable as true. In other words, if an algorithm takes Predicate pred as its argument and first as its iterator argument, it should work correctly in the construct if (pred(*first)){...}. The function object pred shall not apply any non-constant function through the dereferenced iterator. This function object may be a pointer to function, or an object of a type with an appropriate function call operator.
For the above case, I used a lambda expression as function object. This mechanism is widely used in C++. Please read about that.
Unfortunately remove_if will not return any value. There are really several methods to build a solution here.
Let me show you onesolution, by still using the lambda.
#include <iostream>
#include <string>
#include <utility>
#include <list>
std::list<std::pair<std::string, size_t>> poke
{ {"Pikachu", 25},
{"Raticate", 20},
{"Raticate", 20},
{"Bulbasaur", 1},
{"Pikachu", 25},
{"Diglett", 50} };
bool remove(const std::string& s, size_t i) {
bool found = false;
poke.remove_if([&](std::pair<std::string, size_t>& p) {bool rv = (p.first == s and p.second == i); if (rv) found = true; return rv; });
return found;
}
int main() {
if (remove("Raticate", 20))
std::cout << "\nFound\n\n";
else
std::cout << "\nNot Found\n\n";
for (const auto& [s, i] : poke)
std::cout << s << '\t' << i << '\n';
}
It can be done even simpler than Armin Montigny's solution. std::pair<> comes with comparison operators, so you don't need a custom function to check if an element of the list is equal to a given pair:
void remove(const std::string& s, size_t i) {
poke.remove({s, i});
}
Since C++20, std::list's remove() and remove_if() return a count of the number of elements removed. If you need to be compatible with earlier versions, you could always check the result of poke.size() before and after the call to remove() to see if the size of the list has changed.

How to pass std::isspace to function taking unary predicate as argument?

I have the following trim function
std::string trim(const std::string& str, std::function<bool(int ch)> isCharToTrim)
{
auto trimmedStart = std::find_if_not(str.begin(), str.end(), isCharToTrim);
if (trimmedStart == str.end())
{
return "";
}
else
{
auto trimmedEnd = std::find_if_not(str.rbegin(), str.rend(), isCharToTrim);
return std::string(trimmedStart, trimmedEnd.base());
}
}
When I pass std::isspace as second argument, it compiles with MSVC.
But I get an error with gcc: error: cannot resolve overloaded function 'isspace' based on conversion to type 'std::function<bool(int)>'.
Usage of the function that works on MSVC
const auto trimmed = trim(test, std::isspace);
const auto trimmed2 = trim(test, std::not_fn(std::isgraph));
const auto trimmed3 = trim(test, [](int ch) { return ch == ' '; });
What changes can I make to get it to compile on gcc? Change the argument type?
https://godbolt.org/z/81cjvrh7E
You should not use function pointers to functions in the standard library unless they are explicitly addressable functions.
You can wrap them in a lambda:
const auto trimmed = trim(test, [](auto c) { return std::isspace(static_cast<unsigned char>(c)); });
Note that it is not necessary to convert all callables to std::function just to call them or pass them to an algorithm. You can accept any callable by making the function a template:
template <typename C>
std::string trim(const std::string& str, C isCharToTrim);
The error complains about an overload because there is https://en.cppreference.com/w/cpp/locale/isspace in addition to the function you want to pass. Anyhow, strictly speaking the standard merely specifies what happens when you call std::isspace(int). There needs not actually be a function int std::isspace(int), it could be int std::isspace(int,int=42). There can be other overloads present. For this (and perhaps other) reasons it is generally not allowed to take pointers to standard functions.

Function which takes variadic function as parameter

I'm trying to create function which takes variadic function as parameter, but I can't figure out how to do it in a proper way. This is my try:
#include <iostream>
#include <cstdarg>
using namespace std;
int add(int args, ...) {
int res = 0;
va_list ap;
va_start(ap, args);
for(int i=0; i < args; ++i)
res += va_arg(ap, int);
va_end(ap);
return res;
}
int func(int (*func_arg)(int args, ...)) {
return func_arg; //error
}
int main() {
cout << add(2, 1, 2) << endl; //working
cout << func(add(2, 1, 2)); //error
return 0;
}
This here...
func(add(2, 1, 2))
... calls the function add and tries to pass the result into func. That's making a pointer out of an integer without a cast, etc. So you get an error.
To pass the function itself (after the suitable function to pointer conversion) you'd do this:
func(add)
However, your implementation of func tries to return an integer by converting the function pointer. I strongly suspect that's not what you want. If you intend to call the variadic function, you can do this:
int func(int (*func_arg)(int args, ...)) {
return func_arg(2, 1, 2);
}
But that of course hard-codes the arguments. You'd need to work out a slight design change if you wish to allow passing arguments as well.
Having said all that, if you wish to support callers of func passing in anything that may return an integer, you can use the library type std::function to accomplish that. Then your function will become something like this:
int func(std::function<int()> func_arg) {
return func_arg(); //Invoke the callable
}
And the call site will be able to adapt to it with a simple lambda:
func([]{ return add(2, 1, 2); })
Which will come together into the effect you seem intent on achieving.

String array to C++ function

I want to check if a given name is inside an array of possible names. I wrote this small debugging function ( yeah... I know it always return true ) trying to understand why it does not work and why I get the below error.
Code
char[] people_names = ["Mario","Luigi"];
bool lookupTerm (string term, string possible_names[]){
for(const string &possible_name : possible_names)
cout << possible_name << endl;
return true;
}
Error
jdoodle.cpp: In function 'bool lookupTerm(std::__cxx11::string, std::__cxx11::string*)':
jdoodle.cpp:19:38: error: no matching function for call to 'begin(std::__cxx11::basic_string<char>*&)'
I know that it must be really obvious but according to what I have searched for, it should work. Can someone point me in the right direction?
The problem is that when you pass an array to a function, it decays to a pointer to its first element.
It doesn't matter if you attempt to declare the argument as an array, the compiler still translates it as a pointer. string possible_names[] is equal to string* possible_names when you declare arguments.
The simple solution is to use either std::vector or std::array depending on your needs and use-case.
Using std::vector your code would look something like this:
std::vector<std::string> people_names = { "Mario", "Luigi" };
bool lookupTerm(const std::string& term, const std::vector<std::string>& possible_names) {
for (const std::string &possible_name : possible_names)
{
if (possible_name == term)
return true;
}
return false;
}
One line using std::find:
bool lookupTerm(const std::string& term, const std::vector<std::string>& possible_names) {
return std::find(possible_names.begin(), possible_names.end(), term) != possible_names.end();
}
If performance becomes a problem you can increase the performance of this by using a sorted vector (using std::sort) and std::lower_bound:
//at one point:
std::sort(people_names.begin(), people_names.end());
bool lookupTerm(const std::string& term, const std::vector<std::string>& sorted_possible_names) {
//sorted_possible_names must be always sorted when you call this!
auto i = std::lower_bound(sorted_possible_names.begin(), sorted_possible_names.end(), term);
return (i != sorted_possible_names.end() && *i == term);
}

How can I simplify the calling of this function?

I've written (and use) my own string formatting function and I'd like to simplify the usage of the function, in a specific way shown below, but I'm unsure how.
Here's the relevant code:
// Object that can hold a copy of every type I want to print.
// Stores the copy in a union, with an enumeration to identify
// the type. any uses C++ constructors, but could also be implemented
// with C99 designated initializers, like so: https://ideone.com/ElQgBV
struct any
{
...
}
// The string format function requires the variable arguments
// to all be of the 'any' type for type safety and (essential for
// my purposes) positional printing.
// Arguments are accessed with a va_list, so essentially
// the variable arguments are treated as an array of any objects.
char* format_function_(const char* fmt, ...);
// I call the above function with this macro that expands the
// variable arguments and adds a default-constructed sentinel
// at the end. The sentinel is used by the function to count
// how many arguments were passed.
#define format(fmt, ...) format_function_(fmt, __VA_ARGS__, any())
// Calling the function like so, via the above macro...
char* str = format("bits:%4b string:%1 %0 int:%3h float:%2.2\n",
any("world"), any("hello"), any(3.14159f), any(42), any((u8)(1<<4)));
// ...returns this string:
// bits:00010000 string:hello world int:0000002A float:3.14
I'd like to be able to call the function like regular *printf style functions...
char* str = format("bits:%4b string:%1 %0 int:%3h float:%2.2\n",
"world", "hello", 3.14159f, 42, (u8)(1<<4));
...with the use of the any object hidden away, possibly behind another macro.
How can I accomplish this?
Edit/Update The positional arguments are essential for my purposes. Any answer that does not preserve this functionality is not a valid answer.
Since the C++11 standard there's something called parameter packs which makes this very simple:
char* format_function(const char* fmt, ...)
{
...
}
template<typename ...T>
char* format(const char* fmt, T... values)
{
return format_function(fmt, any(values)...);
}
...
char* str = format("bits:%4b string:%1 %0 int:%3h float:%2.2\n",
"world", "hello", 3.14159f, 42, (u8)(1<<4));
Maybe you'ld like something like this? (Alert: C++11 code!)
#include <stdio.h>
inline void format() {}
void format(char ch) {
fputc(ch, stdout);
}
void format(int i) {
if(i < 0) {
fputc('-', stdout);
i = -i;
}
int divider = 1;
while(i / divider >= 10)
divider *= 10;
do {
int digit = i / divider;
i -= divider * digit;
divider /= 10;
fputc('0' + digit, stdout);
} while(divider > 0);
}
void format(const char *str) {
fputs(str, stdout);
}
// TODO: Add more 'format()' overloads here!
template<typename FirstArg, typename... OtherArgs>
inline void format(const FirstArg &first, OtherArgs... others) {
format(first);
format(others...);
}
Then, you can simply...
const char *glorifiedIndex(int index) {
switch(index % 10) {
case 1:
return "st";
case 2:
return "nd";
case 3:
return "rd";
default:
return "th";
}
}
int main(int argc, const char *const argv[]) {
format("Hello, world!\n");
format("My name is ", argv[0], ", and I was given ", argc - 1, " argument", argc != 2 ? "s" : "", ".\n\n");
for(int i = 1; i < argc; i++)
format(i, glorifiedIndex(i), " argument: \"", argv[i], "\"\n");
format("Goodbye, world!\n");
}
This is a more flexible and elegant model, for the following reasons:
Semantically safe.
Type safe.
No <cstdarg> stuff.
No any stuff.
No incredibly badly-designed iostream stuff.
It's too simple to implemet, and I mean too much :). Compare this few lines of code with a typical 3000+ lines long printf.c. The difference is in several orders of magnitude!
You may have nostalgic moments relating with Java and Python.
If you change the type of any expression for whatever reason (i.e, int to unsigned), the function accomodates itself to this.
(Both good and evil) compiler optimizations can kick in easily.
The user of the library may extended the abilities of the format() function by means of overloading it with user-defined types.
This imposibilites the use of dynamic formats (this is intended for obvious security reasons).
This forces you to create special functions for what I call bit-printing, i.e, printing in a machine-parsable way, rather than human-readable as format() did, does, and will do.
You may use overloading features to extend this list yourself :).