0

I want to write a callback like this

template<typename T>
T GetValue(T (*CallBack) (const string), string in)
{
    T value;

    try
    {
        value = CallBack(in);
    }
    catch(std::invalid_argument &e)///if no conversion could be performed
    {
        cout << "Error: invalid argument: --> " + string(e.what());
        exit(-1);
    }
    return value;
}

int main()
{
    int integer=0;
    string data;
    cin>>data;
    integer=GetValue<int>(&std::stoi, data);
    return 0;
}

but it does not works. I have the following error.

error: cannot convert "|unresolved overloaded function type|" to "int (^)(std::string)" {aka int (^)(std::__cxx11::basic_string)}

I tried other ways too. Like this:

class Object;
typedef int (Object::*CallBack)(const string&, std::size_t*, int);

Or like this:

    typedef int (std::*FCAST)(const string&);
    std::function<int(const string&)> f = (FCAST)&std::stoi;

error: address of overloaded function with no contextual type information|

But i had not success. ¿Someone knows how to do it?

Thank you so much!!

Etienne de Martel
  • 34,692
  • 8
  • 91
  • 111
Iván Rodríguez
  • 447
  • 4
  • 10
  • 2
    std::stoi doesn't expect string passed as call by value I guess. https://en.cppreference.com/w/cpp/string/basic_string/stol. But of course that doesn't seem to be the root cause of this issue. – kiner_shah Jan 04 '22 at 04:20
  • Yes, i think so too. Than you so much for your response and the link – Iván Rodríguez Jan 04 '22 at 04:26
  • 4
    `std::stoi` has a type. It is not `int (*) (const string)`. It is not `int (Object::*)(const string&, std::size_t*, int)`. It is not `int(const string&)`. Just use the right type. https://godbolt.org/z/Mvh4bqhxP Note that it is **undefined behaviour** to take an address of most standard library functions. – n. m. could be an AI Jan 04 '22 at 04:29
  • It works. Thank you so much. Very appreciated. – Iván Rodríguez Jan 04 '22 at 04:38

2 Answers2

2

Link: https://godbolt.org/z/69fTzW36z

You have to use the correct function signature - the one which stoi has.

As per this link: https://en.cppreference.com/w/cpp/string/basic_string/stol, the signrature is int stoi(const string&, size_t* pos = nullptr, int base = 10)

So making the changes (see // CHANGE HERE)

#include <iostream>
using namespace std;

// CHANGE HERE: see the function arguments to Callback
template<typename T>
T GetValue(T (*CallBack) (const string&, size_t* pos, int base), const string& in)
{
    T value;

    try
    {
        // CHANGE HERE: pass default arguments when calling the function
        value = CallBack(in, nullptr, 10);
    }
    catch(std::invalid_argument &e)///if no conversion could be performed
    {
        cout << "Error: invalid argument: --> " + string(e.what());
        exit(-1);
    }
    return value;
}

int main()
{
    int integer=0;
    string data = "1234";
    //cin>>data;
    integer=GetValue<int>(std::stoi, data);
    cout << integer << endl;
    return 0;
}

As mentioned in the comments, it's better not to use standard library functions directly as function callbacks. Rather you may implement your own logic or you can use some other way like lambda functions, something like:

#include <iostream>
using namespace std;

template<typename T>
T GetValue(T (*CallBack) (const string&), const string& in)
{
    T value;

    try
    {
        value = CallBack(in);
    }
    catch(std::invalid_argument &e)///if no conversion could be performed
    {
        cout << "Error: invalid argument: --> " + string(e.what());
        exit(-1);
    }
    return value;
}

int main()
{
    string data = "1234";
    //cin>>data;
    int integer = GetValue<int>([](const string& s) { return stoi(s); }, data);
    cout << integer << endl;
    string data2 = "12345678900";
    long l = GetValue<long>([](const string& s) { return stol(s); }, data2);
    cout << l << endl;
    return 0;
}

Link: https://godbolt.org/z/31oKx5cjE

kiner_shah
  • 3,939
  • 7
  • 23
  • 37
  • 2
    Note that `std::stoi` is not designated an [addressable function](https://en.cppreference.com/w/cpp/language/extending_std#Addressing_restriction). Use a lambda instead to avoid unspecified behavior. See also https://stackoverflow.com/q/55687044/1458097 – heap underrun Jan 04 '22 at 04:39
  • Yes that's correct. Let me try to make some changes. – kiner_shah Jan 04 '22 at 04:42
2

If you look at std::stoi, the signature is int(const std::string&, std::size_t*, int ); So, your callback needs to be of the right type. If you want to use the default parameter value, you can use lambdas.

GetValue<int>([](std::string s) { return std::stoi(s); }, data);

Deev
  • 471
  • 2
  • 9