compile error: no matching function for call to 'transform(

The first example has no class definitions, it compiles.
The second example has the same code in class definitions, it does not compile.
Why does it not compile? I am stumped.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <algorithm>
#include <string>
#include <vector>
using namespace std;

int char2int(char c)
{
	return c - '0';
}

int main()
{
	string str = "234";
	vector<int> p;
	p.reserve(str.size());

	transform(str.begin(), str.end(), back_inserter(p), char2int);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <algorithm>
#include <string>
#include <vector>
using namespace std;

class Test
{
    public:
	int char2int(char c);
	void generate();
};

int Test::char2int(char c)
{
	return c - '0';
}

void Test::generate()
{
	string str = "234";
	vector<int> p;
	p.reserve(str.size());

	transform(str.begin(), str.end(), back_inserter(p), Test::char2int);

}
Test t;

int main()
{
	t.generate();
}

The last example gets this compile error:
D:\keyboard4_test>g++ Test3.cpp
Test3.cpp: In member function 'void Test::generate()':
Test3.cpp:24:68: error: no matching function for call to 'transform(std::basic_s
tring<char>::iterator, std::basic_string<char>::iterator, std::back_insert_itera
tor<std::vector<int> >, <unresolved overloaded function type>)'
  transform(str.begin(), str.end(), back_inserter(p), Test::char2int);
                                                                    ^
Test3.cpp:24:68: note: candidates are:
In file included from c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\algorithm:62:0,

                 from Test3.cpp:1:
c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\bits\stl_algo.h:4938:5: note: _OIter
std::transform(_IIter, _IIter, _OIter, _UnaryOperation) [with _IIter = __gnu_cxx
::__normal_iterator<char*, std::basic_string<char> >; _OIter = std::back_insert_
iterator<std::vector<int> >; _UnaryOperation = int (Test::*)(char)]
     transform(_InputIterator __first, _InputIterator __last,
     ^
c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\bits\stl_algo.h:4938:5: note:   no kn
own conversion for argument 4 from '<unresolved overloaded function type>' to 'i
nt (Test::*)(char)'
c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\bits\stl_algo.h:4975:5: note: templat
e<class _IIter1, class _IIter2, class _OIter, class _BinaryOperation> _OIter std
::transform(_IIter1, _IIter1, _IIter2, _OIter, _BinaryOperation)
     transform(_InputIterator1 __first1, _InputIterator1 __last1,
     ^
c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\bits\stl_algo.h:4975:5: note:   templ
ate argument deduction/substitution failed:
Test3.cpp:24:68: note:   candidate expects 5 arguments, 4 provided
  transform(str.begin(), str.end(), back_inserter(p), Test::char2int);
                                                                    ^

Thank you for looking into this.
In order to use the member function Test::char2int() as you currently do, it must be declared as static.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <algorithm>
#include <string>
#include <vector>
using namespace std;

class Test
{
    public:
	static int char2int(char c);
	void generate();
};

int Test::char2int(char c)
{
	return c - '0';
}

void Test::generate()
{
	string str = "234";
	vector<int> p;
	p.reserve(str.size());

	transform(str.begin(), str.end(), back_inserter(p), Test::char2int);

}
Test t;

int main()
{
	t.generate();
}


I generally don't just give out answers, but this is a funny one that I honestly have no clue how to guide you toward subtly. Sorry.

This is a result of a curious little hitch in how C++ implements member functions. Member functions have a hidden implicit first parameter, which is generally used for this. This means that your member function underneath actually takes two arguments, but C++ handles the first for you. That means your member function cannot be used as you're trying to use it.

There are four ways around this issue.

1: Make char2int a normal function.

2: Make char2int static.

3: Create a lambda that wraps the member function.

4: Use std::bind in the <functional> header to bind this to the first argument slot.

I personally would use method 4, but the others are valid as well (though 3 is a bit hackish).

-Albatross
Thanks for the explanation. this blows my mind.
I am still trying to understand how that works though.
Why does this->char2int not work?
Last edited on
Why does this->char2int not work?

Because, as Albatross already explained, non-static Test::char2int() is not a "normal" function.

It is a member function that requires an object to exist in order to be called.
In other words it is treated specially (and possibly being passed an extra, hidden parameter).

However when you declare it as static it basically becomes a regular function whose namespace is the Test class.

http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/topic/com.ibm.xlcpp8l.doc/language/ref/cplr039.htm
http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/topic/com.ibm.xlcpp8l.doc/language/ref/cplr035.htm

3: Create a lambda that wraps the member function.

4: Use std::bind in the <functional> header to bind this to the first argument slot.

I personally would use method 4, but the others are valid as well (though 3 is a bit hackish).

Point 3 is ugly but it's a somewhat sensible approach in my opinion.

Point 4, on the other hand, is the hackish one. You rely on low level details and people not knowing them may have problems understanding your code.
http://en.cppreference.com/w/cpp/utility/functional/bind

Care to give examples for these two points, for clarity?
Last edited on
Topic archived. No new replies allowed.