Reputation: 6350
The following code:
$ cat test02.cpp
#include <string>
#include <numeric>
#include <cstdlib>
#include <list>
#include <iostream>
struct myadd :
public std::binary_function
<const std::string&,const std::string&,std::string>
{
std::string operator () (const std::string& x,const std::string& y) const {
return x+" "+y;
}
};
struct mymul :
public std::binary_function
<const std::string&,const std::string&,std::string>
{
std::string operator () (const std::string& x,const std::string& y) const {
return x+y;
}
};
std::string spliceme(
const std::list <std::string>& list1,
const std::list <std::string>& list2,
const std::binary_function
<const std::string&,const std::string&,std::string>& add,
const std::binary_function
<const std::string&,const std::string&,std::string>& mul
) {
return std::inner_product(list1.cbegin(),list1.cend(),list2.cbegin(),
std::string(""),add,mul);
}
int main() {
std::list <std::string> list1;
list1.emplace_back("First");
list1.emplace_back("Second");
list1.emplace_back("Third");
std::list <std::string> list2;
list2.emplace_back("Foerst");
list2.emplace_back("Annen");
list2.emplace_back("Tredje");
std::string result = spliceme(list1,list2,myadd(),mymul());
std::cout << result << std::endl;
return EXIT_SUCCESS;
}
Generates the compiler error:
g++ -std=c++0x test02.cpp -o test02
In file included from /usr/lib/gcc/i686-pc-linux-gnu/4.6.3/include/g++-v4/numeric:62:0,
from test02.cpp:2:
/usr/lib/gcc/i686-pc-linux-gnu/4.6.3/include/g++-v4/bits/stl_numeric.h: In function '_Tp std::inner_product(_InputIterator1, _InputIterator1, _InputIterator2, _Tp, _BinaryOperation1, _BinaryOperation2) [with _InputIterator1 = std::_List_const_iterator<std::basic_string<char> >, _InputIterator2 = std::_List_const_iterator<std::basic_string<char> >, _Tp = std::basic_string<char>, _BinaryOperation1 = myadd, _BinaryOperation2 = std::binary_function<const std::basic_string<char>&, const std::basic_string<char>&, std::basic_string<char> >]':
test02.cpp:29:101: instantiated from here
/usr/lib/gcc/i686-pc-linux-gnu/4.6.3/include/g++-v4/bits/stl_numeric.h:218:2: error: no match for call to '(std::binary_function<const std::basic_string<char>&, const std::basic_string<char>&, std::basic_string<char> >) (const std::basic_string<char>&, const std::basic_string<char>&)'
make: *** [all] Error 1
The issue occurs on the line:
return std::inner_product(list1.cbegin(),list1.cend(),list2.cbegin(),
std::string(""),add,mul);
If I instantiate the classes myadd and mymul directly:
return std::inner_product(list1.cbegin(),list1.cend(),list2.cbegin(),
std::string(""),myadd(),mymul());
Everything compiles and runs correctly. What's wrong with the way I'm passing in the functions add and mul into the function spliceme?
Upvotes: 0
Views: 349
Reputation: 4863
std::binary_function
was a convenience template for adding three typedefs to your function object. It was never intended to be used as a base class in function signatures, because all that happens is your object gets sliced. It has been deprecated in C++11 and should no longer be used. Yakk gives a great answer on what you should be doing. If you really need those typedefs (first_argument_type
, second_argument_type
and result_type
), add them yourself.
Upvotes: 1
Reputation: 275800
Either this:
std::string spliceme(
const std::list <std::string>& list1,
const std::list <std::string>& list2,
const std::function<std::string(const std::string&,const std::string&)>& add,
const std::function<std::string(const std::string&,const std::string&)>& mul
) {
return std::inner_product(list1.cbegin(),list1.cend(),list2.cbegin(),
std::string(""),add,mul);
}
or this:
template<typename Add, typename Mul>
std::string spliceme(
const std::list <std::string>& list1,
const std::list <std::string>& list2,
const Add& add,
const Mul& mul
) {
return std::inner_product(list1.cbegin(),list1.cend(),list2.cbegin(),
std::string(""),add,mul);
}
makes your code work. The first uses type erased functions, the second uses template
functors. The first lets you split your body out of the header, the second allows for improved inlineing.
Upvotes: 3
Reputation: 10594
std::string spliceme(
const std::list <std::string>& list1,
const std::list <std::string>& list2,
const std::binary_function
<const std::string&,const std::string&,std::string>& add,
const std::binary_function
<const std::string&,const std::string&,std::string>& mul
)
should be:
std::string spliceme(
const std::list <std::string>& list1,
const std::list <std::string>& list2,
const myadd& add,
const mymul& mul
) {
because operator() is not virtual function
Upvotes: 2