Passing std algorithm. Template deducing [duplicate] - c++

This question already has answers here:
Why can't "transform(s.begin(),s.end(),s.begin(),tolower)" be complied successfully?
(5 answers)
Closed 6 years ago.
I was trying to make this small example work
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<char> v{'a', 'b', 'c', 'd'};
std::transform(v.begin(), v.end(), v.begin(), std::toupper);
std::for_each(v.begin(), v.end(), [](char & c) {
std::cout << c << " ";
});
}
I think it's obvious, what i'm trying to achive. However, I get these errors
||=== Build file: "no target" in "no project" (compiler: unknown) ===|
C:\Users\vitaly.bushaev\Documents\vk cup\1.cpp||In function 'int main()':|
C:\Users\vitaly.bushaev\Documents\vk cup\1.cpp|8|error: no matching function for call to 'transform(std::vector<char>::iterator, std::vector<char>::iterator, std::vector<char>::iterator, <unresolved overloaded function type>)'|
C:\Users\vitaly.bushaev\Documents\vk cup\1.cpp|8|note: candidates are:|
C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\4.9.2\include\c++\bits\stl_algo.h|4152|note: template<class _IIter, class _OIter, class _UnaryOperation> _OIter std::transform(_IIter, _IIter, _OIter, _UnaryOperation)|
C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\4.9.2\include\c++\bits\stl_algo.h|4152|note: template argument deduction/substitution failed:|
C:\Users\vitaly.bushaev\Documents\vk cup\1.cpp|8|note: couldn't deduce template parameter '_UnaryOperation'|
C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\4.9.2\include\c++\bits\stl_algo.h|4189|note: template<class _IIter1, class _IIter2, class _OIter, class _BinaryOperation> _OIter std::transform(_IIter1, _IIter1, _IIter2, _OIter, _BinaryOperation)|
C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\4.9.2\include\c++\bits\stl_algo.h|4189|note: template argument deduction/substitution failed:|
C:\Users\vitaly.bushaev\Documents\vk cup\1.cpp|8|note: candidate expects 5 arguments, 4 provided|
||=== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|
So I'm reading this and I understand the error, but i can't understand why is it happening. Sure this works fine:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<char> v{'a', 'b', 'c', 'd'};
using it = std::vector<char>::iterator;
std::transform<it, it, int (int)>(v.begin(), v.end(), v.begin(), std::toupper);
std::for_each(v.begin(), v.end(), [](char & c) {
std::cout << c << " ";
});
}
So here's the question:
1) Why c++ can't deduce template parameter here ?
2) Is there a way around that, to not specify types ?

There is more than one overload for std::toupper.
Template deduction happens before overload selection, so you have to either be specific or wrap the call in a lambda or function object.
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<char> v{'a', 'b', 'c', 'd'};
// method 1
struct make_upper
{
int operator()(int ch) const { return std::toupper(ch); }
};
std::transform(v.begin(), v.end(), v.begin(), make_upper());
// method 2
std::transform(v.begin(), v.end(), v.begin(), [](auto&& ch) { return std::toupper(ch); });
}
references:
http://en.cppreference.com/w/cpp/locale/toupper
http://en.cppreference.com/w/cpp/string/byte/toupper

Related

Why can't template argument be resolved from std::addressof<int>?

Clang and GCC (except for MSVC) fail to resolve a template argument when it's passed std::addressof<int> as an argument to the template function. The following is an example of such error:
std::vector<int> v{1,2,3,4,5};
std::vector<int*> pv(iv.size());
std::transform(v.begin(), v.end(), pv.begin(), std::addressof<int>);
Clang:
<source>:8:5: error: no matching function for call to 'transform'
std::transform(iv.begin(), iv.end(), piv.begin(), std::addressof<int>);
^~~~~~~~~~~~~~
/opt/compiler-explorer/clang-5.0.0/bin/../include/c++/v1/algorithm:2028:1: note: candidate template ignored: couldn't infer template argument '_UnaryOperation'
transform(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _UnaryOperation __op)
^
GCC:
/opt/compiler-explorer/gcc-7.2.0/include/c++/7.2.0/bits/stl_algo.h:4295:5: note: template argument deduction/substitution failed:
<source>:8:74: note: could not resolve address from overloaded function 'addressof<int>'
std::transform(iv.begin(), iv.end(), piv.begin(), std::addressof<int>);
^
That error would make sense if the argument was instead an std::addressof, because the UnaryOperator template parameter would be ambiguous. However, the compiler doesn't need to deduce what T is in std::addressof<int>, I'd except no ambiguity here.
Here's a working example of my expectations (compiles on Clang 5 and GCC 7.2):
template <typename T>
T* addrof(T& a)
{
return __builtin_addressof(a);
}
template <typename F, typename T>
void foo(F f, T& a)
{
f(a);
}
int main()
{
int a = 42;
foo(addrof<int>, a);
}
My doubt is: why can't std::transforms template argument be deduced from std::addressof<int>?
Yes, it doesn't work in your example because there are two overloads for each template std::addressof since C++ 17 (one getting the address and a deleted version which takes an rvalue reference), and it is ambiguous for the compiler which one to choose. Easiest solution is to use lambda:
#include <vector>
#include <algorithm>
void foo() {
std::vector<int> v{1,2,3,4,5};
std::vector<int*> pv(v.size());
std::transform(v.begin(), v.end(), pv.begin(),
[](int& i) { return std::addressof(i);});
}
Those overloads are listed here: http://en.cppreference.com/w/cpp/memory/addressof
The other option is to use cast, but it is just ugly, and Thy Should Prefer Lambdas! Nevertheless, will provide for completness:
#include <vector>
#include <algorithm>
void foo() {
std::vector<int> v{1,2,3,4,5};
std::vector<int*> pv(v.size());
std::transform(v.begin(), v.end(), pv.begin(),
static_cast<int* (*)(int&) >(std::addressof<int>));
}

Transform a vector of int to a vector of str

I'm trying to convert a vector<int> to a vector<string>. Using std::transform I used std::to_string to convert the int to string but I keep getting an error. Here's my code
#include <vector>
#include <iostream>
#include <algorithm>
#include <string>
int main(){
std::vector<int> v_int;
std::vector<std::string> v_str;
for(int i = 0;i<5;++i)
v_int.push_back(i);
v_str.resize(v_int.size());
std::transform(v_int.begin(),v_int.end(),v_str.begin(),std::to_string);
}
but I'm getting this error
no matching function for call to 'transform'
std::transform(v_int.begin(),v_int.end(),v_str.begin(),std::to_string);
^~~~~~~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/algorithm:1951:1: note:
candidate template ignored: couldn't infer template argument
'_UnaryOperation'
transform(_InputIterator __first, _InputIterator __last, _OutputIterato...
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/algorithm:1961:1: note:
candidate function template not viable: requires 5 arguments, but 4 were
provided
transform(_InputIterator1 __first1, _InputIterator1 __last1, _InputItera...
std::to_string is an overloaded function, so you'll need to provide a cast to disambiguate
std::transform(v_int.begin(),v_int.end(),v_str.begin(),
static_cast<std::string(*)(int)>(std::to_string));
Or use a lambda
std::transform(v_int.begin(),v_int.end(),v_str.begin(),
[](int i){ return std::to_string(i); });

What are the function requirements to use as the predicate in the find_if from the <algorithm> library?

I can't tell if I'm just missing something obvious here but I cannot seem to get find_if to work.
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
bool isspace(char c)
{
return c == ' ';
}
int main()
{
string text = "This is the text";
string::iterator it = find_if(text.begin(), text.end(), isspace);
cout << *it << endl;
return 0;
}
I've looked at the example here, http://www.cplusplus.com/reference/algorithm/find_if/, which compiles and runs but I cannot see the difference between that and my program other than the vector -> string thing but I don't see why that would make a difference.
I know cctype has the better functions for isspace but I wanted to make sure that wasn't messing me up.
My error:
test.cpp: In function ‘int main()’:
test.cpp:16:68: error: no matching function for call to ‘find_if(std::basic_string<char>::iterator, std::basic_string<char>::iterator, <unresolved overloaded function type>)’
string::iterator it = find_if(text.begin(), text.end(), isspace);
^
test.cpp:16:68: note: candidate is:
In file included from /usr/include/c++/4.8/algorithm:62:0,
from test.cpp:3:
/usr/include/c++/4.8/bits/stl_algo.h:4456:5: note: template<class _IIter, class _Predicate> _IIter std::find_if(_IIter, _IIter, _Predicate)
find_if(_InputIterator __first, _InputIterator __last,
^
/usr/include/c++/4.8/bits/stl_algo.h:4456:5: note: template argument deduction/substitution failed:
test.cpp:16:68: note: couldn't deduce template parameter ‘_Predicate’
string::iterator it = find_if(text.begin(), text.end(), isspace);
^
The key part of the error is:
test.cpp:16:68: error: no matching function for call to ‘find_if(
std::basic_string<char>::iterator,
std::basic_string<char>::iterator,
<unresolved overloaded function type>)’ // <==
Unresolved overloaded function type!? That's because you defined:
bool isspace(char );
But there is already one named isspace:
bool isspace(int );
and another named std::isspace that you bring in with using:
template <class charT>
bool isspace(charT, const locale&);
And the template can't know which one it is you want. So you can either specify it explicitly:
string::iterator it = find_if(
text.begin(),
text.end(),
static_cast<bool(*)(char)>(isspace)); // make sure yours gets called
Or, simpler, just change your name.
Or, simplest, just delete yours and stop using namespace std;. That way, isspace unambiguously references exactly the one function you wanted to use in the first place.

find() not working in C++ Header

I have a vector in my Header file, and I'm trying to do a bool function that returns the find() function, but it is giving me an error.
vector<string> reservedWord{
....
....
....
};
bool function
bool isReservedWord(string str)
{
return find(reservedWord.begin(), reservedWord.end(), str) != reservedWord.end();
}
I tried it both without the last != reservedWord.end) and also without.
The errors given are these:
||=== Build: Release in compilers (compiler: GNU GCC Compiler) ===|
E:\University\compilers\reservedWords.h||In function 'bool isReservedWord(std::string)':|
E:\University\compilers\reservedWords.h|40|error: no matching function for call to 'find(std::vector<std::basic_string<char> >::iterator, std::vector<std::basic_string<char> >::iterator, std::string&)'|
E:\University\compilers\reservedWords.h|40|note: candidate is:|
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\bits\streambuf_iterator.h|371|note: template<class _CharT2> typename __gnu_cxx::__enable_if<std::__is_char<_CharT2>::__value, std::istreambuf_iterator<_CharT2, std::char_traits<_CharT> > >::__type std::find(std::istreambuf_iterator<_CharT2, std::char_traits<_CharT> >, std::istreambuf_iterator<_CharT2, std::char_traits<_CharT> >, const _CharT2&)|
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\bits\streambuf_iterator.h|371|note: template argument deduction/substitution failed:|
E:\University\compilers\reservedWords.h|40|note: '__gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >' is not derived from 'std::istreambuf_iterator<_CharT2, std::char_traits<_CharT> >'|
E:\University\compilers\reservedWords.h|41|warning: control reaches end of non-void function [-Wreturn-type]|
||=== Build failed: 1 error(s), 1 warning(s) (0 minute(s), 0 second(s)) ===|
Here's a working example. Look at how your code is different. Ask questions as required. :-)
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
std::vector<std::string> g_reserved
{
"the",
"quick",
"brown",
"fox",
"jumps",
"over",
"the",
"lazy",
"dog"
};
bool IsReserved(const std::string &s)
{
return g_reserved.end() !=
std::find(g_reserved.cbegin(), g_reserved.cend(), s);
}
int main()
{
std::cout << std::boolalpha
<< IsReserved("fox")
<< ' '
<< IsReserved("zebra")
<< std::endl;
return 0;
}
I got the same compilation error when <string> was included but <algorithm> was not. In that case the compiler only sees the declaration of
std::find(std::istreambuf_iterator<_CharT>, std::istreambuf_iterator<_CharT>, const _CharT2&)
and quits with this error.
To fix this, add
#include <algorithm>

Boost Graph example doesn't compile.

I took the code from
http://www.boost.org/doc/libs/1_54_0/libs/graph/doc/edge_list.html
included my header,
#include <iostream> // for std::cout
#include <utility> // for std::pair
#include <algorithm> // for std::for_each
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/edge_list.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/bellman_ford_shortest_paths.hpp>
#include <boost/graph/johnson_all_pairs_shortest.hpp>
#include <fstream>
#include <ctime>
using namespace boost;
int main(){
enum { u, v, x, y, z, N };
char name[] = { 'u', 'v', 'x', 'y', 'z' };
typedef std::pair<int,int> E;
E edges[] = { E(u,y), E(u,x), E(u,v),
E(v,u),
E(x,y), E(x,v),
E(y,v), E(y,z),
E(z,u), E(z,x) };
int weight[] = { -4, 8, 5,
-2,
9, -3,
7, 2,
6, 7 };
typedef boost::edge_list<E*> Graph;
Graph g(edges, edges + sizeof(edges) / sizeof(E));
std::vector<int> distance(N, std::numeric_limits<short>::max());
std::vector<int> parent(N,-1);
distance[z] = 0;
parent[z] = z;
bool r = boost::bellman_ford_shortest_paths(g, int(N), weight,
distance.begin(),
parent.begin());
if (r)
for (int i = 0; i < N; ++i)
std::cout << name[i] << ": " << distance[i]
<< " " << name[parent[i]] << std::endl;
else
std::cout << "negative cycle" << std::endl;
return 0;
}
compile with
g++ -O3 boostexampl.cpp -I/user/include/
I got this error
make -k
g++ -O3 boostexampl.cpp -I/user/include/
boostexampl.cpp: In function ‘int main()’:
boostexampl.cpp:40:61: error: no matching function for call to ‘bellman_ford_shortest_paths(Graph&, int, int [10], std::vector<int>::iterator, std::vector<int>::iterator)’
boostexampl.cpp:40:61: note: candidates are:
In file included from boostexampl.cpp:7:0:
/usr/local/include/boost/graph/bellman_ford_shortest_paths.hpp:91:8: note: template<class EdgeListGraph, class Size, class WeightMap, class PredecessorMap, class DistanceMap, class BinaryFunction, class BinaryPredicate, class BellmanFordVisitor> bool boost::bellman_ford_shortest_paths(EdgeListGraph&, Size, WeightMap, PredecessorMap, DistanceMap, BinaryFunction, BinaryPredicate, BellmanFordVisitor)
/usr/local/include/boost/graph/bellman_ford_shortest_paths.hpp:91:8: note: template argument deduction/substitution failed:
boostexampl.cpp:40:61: note: candidate expects 8 arguments, 5 provided
In file included from boostexampl.cpp:7:0:
/usr/local/include/boost/graph/bellman_ford_shortest_paths.hpp:210:8: note: template<class EdgeListGraph, class Size, class P, class T, class R> bool boost::bellman_ford_shortest_paths(EdgeListGraph&, Size, const boost::bgl_named_params<P, T, R>&)
/usr/local/include/boost/graph/bellman_ford_shortest_paths.hpp:210:8: note: template argument deduction/substitution failed:
boostexampl.cpp:40:61: note: mismatched types ‘const boost::bgl_named_params<P, T, R>’ and ‘int [10]’
In file included from boostexampl.cpp:7:0:
/usr/local/include/boost/graph/bellman_ford_shortest_paths.hpp:222:8: note: template<class EdgeListGraph, class Size> bool boost::bellman_ford_shortest_paths(EdgeListGraph&, Size)
/usr/local/include/boost/graph/bellman_ford_shortest_paths.hpp:222:8: note: template argument deduction/substitution failed:
boostexampl.cpp:40:61: note: candidate expects 2 arguments, 5 provided
In file included from boostexampl.cpp:7:0:
/usr/local/include/boost/graph/bellman_ford_shortest_paths.hpp:229:8: note: template<class VertexAndEdgeListGraph, class P, class T, class R> bool boost::bellman_ford_shortest_paths(VertexAndEdgeListGraph&, const boost::bgl_named_params<T, Tag, Base>&)
/usr/local/include/boost/graph/bellman_ford_shortest_paths.hpp:229:8: note: template argument deduction/substitution failed:
boostexampl.cpp:40:61: note: mismatched types ‘const boost::bgl_named_params<T, Tag, Base>’ and ‘int’
make: *** [examp] Error 1
make: Target `main' not remade because of errors.
Compilation exited abnormally with code 2 at Sat Oct 5 14:24:35
I am kind of stuck here. Any help would be appreciated. Sorry I provides the full code, but I don't know where is problem is. Is boost examples guaranteed to work? did they change the interface but didn't change on-line example? Or I didn't include headers.