I have the following code.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
template <typename Type> inline Type max(Type t1, Type t2) {
return t1 > t2 ? t1 : t2;
}
template <typename Type> inline Type max(const std::vector<Type> &vec) {
return *std::max_element(vec.begin(),vec.end());
}
template <typename Type> inline Type max(const Type *parray, int size) {
return *std::max_element(parray,parray+size);
}
int main(int argc, char *argv[]) {
std::string sarray[] = {"we","were","her","pride","of","ten"};
std::vector<std::string> svec(sarray,sarray+6);
int iarray[] = {12,70,2,169,1,5,29};
std::vector<int> ivec(iarray,iarray+7);
float farray[] = {2.5,24.8,18.7,4.1,23.9};
std::vector<float> fvec(farray,farray+5);
int imax = max(max(ivec),max(iarray,7));
float fmax = max(max(fvec),max(farray,5));
std::string smax = max(max(svec),max(sarray,6));
std::cout << "imax should be 169 -- found: " << imax << '\n'
<< "fmax should be 24.8 -- found: " << fmax << '\n'
<< "smax should be were -- found: " << smax << '\n';
return 0;
}
I am attempting to implement two simple template functions to output the max element of a vector and an array. However, I am receiving the following error when the type is a string.
error: call of overloaded 'max(std::string, std::string)' is ambiguous
Why is this occuring, and what is the best way to remedy it?
The problem is that the compiler is finding multiple matching definitions of max via ADL and it doesn't know which to choose.
Try changing the call to max to use its qualified-id:
std::string smax = ::max(max(svec),max(sarray,6));
Your code
std::string smax = max(max(svec),max(sarray,6));
translates to:
std::string smax = max(string ,string );
After max(svec) and max(sarray,6) are evaluated using your templates. Now here the problem arises:
The standard library already comes with a templated max() function. The compiler will be unable to tell whether you want your version of max() or std::max().
Now you will ask why it worked for integers and floats. Answer is in this line you are specifically mentioning std::string. Hence the compiler is getting confused.
There can be work arounds. But since you need the best solution, I would say rename your max function say MAximum.
Why is this occuring?
The compiler error already tells you why. It does not know which version of max to use.
note: candidates are:
main.cpp:6:38: note: Type max(Type, Type) [with Type = std::basic_string]
...
/usr/include/c++/4.7/bits/stl_algobase.h:210:5: note: const _Tp& std::max(const _Tp&, const _Tp&) [with _Tp = std::basic_string]
Solution:
either explicitely call your max function or just call std::max (which already exists, so why would you want to reimplement it?).
Additionally, there is one ; too much after << "fmax should be 24.8 -- found: " << fmax << '\n'
Related
I'm trying to map string to function pointer, so that I can call the function with iter->second(arg) instead of if-else.
I have written a simple one without class, and it works as expected.
But when I modify it as below, it shows compile errors.
#include <functional>
#include <iostream>
#include <unordered_map>
#include <string>
using std::string;
class A{
private:
int a(int num, string s) { return s.size() + num; }
int b(int num, string s) { return num - s.size(); }
public:
void ido(string str){
typedef std::function<int(int, string)> process_func;
std::unordered_map<string, process_func> m;
m.insert(std::make_pair<string, process_func>("a", &A::a));
// using std::placeholders::_1;
// m.insert(std::make_pair<string, process_func>("a", std::bind(&A::a, this, _1)));
// m["a"] = std::bind(&A::a, this, _1);
// m.insert({{"a", &A::a}, {"b", &A::b}});
auto x = m.find(str);
if(x == m.end()) {
std::cout << "Not supported!" << std::endl;
}
std::cout << x->second(10, "hello") << std::endl;
}
};
int main(int argc, char* argv[]) {
A a;
a.ido(string(argv[1]));
return 0;
}
The errors are:
function.cc: In member function ‘void A::ido(std::string)’:
function.cc:17:65: error: no matching function for call to ‘make_pair(const char [2], int (A::*)(int, std::string))’
m.insert(std::make_pair<string, process_func>("a", &A::a));
^
function.cc:17:65: note: candidate is:
In file included from /usr/include/c++/4.8.2/utility:70:0,
from /usr/include/c++/4.8.2/tuple:38,
from /usr/include/c++/4.8.2/functional:55,
from function.cc:1:
/usr/include/c++/4.8.2/bits/stl_pair.h:276:5: note: template<class _T1, class _T2> constexpr std::pair<typename std::__decay_and_strip<_Tp>::__type, typename std::__decay_and_strip<_T2>::__type> std::make_pair(_T1&&, _T2&&)
make_pair(_T1&& __x, _T2&& __y)
^
/usr/include/c++/4.8.2/bits/stl_pair.h:276:5: note: template argument deduction/substitution failed:
function.cc:17:65: note: cannot convert ‘&A::a’ (type ‘int (A::*)(int, std::string) {aka int (A::*)(int, std::basic_string<char>)}’) to type ‘std::function<int(int, std::basic_string<char>)>&&’
m.insert(std::make_pair<string, process_func>("a", &A::a));
What does the error mean? How to fix it?
While your functions 'a' and 'b' do not depend on 'this' (they do not access anything inside class A), the compiler is not smart enough to deduce this. So the error means that you are trying to convert 'pointer to method' to 'pointer to function', which is incorrect conversion. 'Pointer to method' requires and object to be called on. You need to declare methods 'a' and 'b' as 'static' to indicate that they are actually standalone functions, not methods of the class.
Take this example:
#include <vector>
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cmath>
void PrintVec(const std::vector<float>&);
int main(int argc, char * argv[]){
float vals[] = {-1.2,0.0,1.2};
std::vector<float> test(vals, vals + sizeof(vals) / sizeof(float));
std::vector<float> absTest(3);
std::transform(test.begin(), test.end(), absTest.begin(), std::abs<float>());
PrintVec(test);
PrintVec(absTest);
return 0;
}
void PrintVec(const std::vector<float> &vec){
for (unsigned int i = 0; i < vec.size(); ++i){
std::cout << vec[i] << '\n';
}
return;
}
Using both gcc 4.3.4 and VS 2013 I get compiler errors. For gcc its:
testTransformAbs.cpp:15: error: expected primary-expression before 'float'
For VS 2013 its:
error C2062: type 'float' unexpected
If I remove <float> then I get this error:
testTransformAbs.cpp:15: error: no matching function for call to 'abs()'
/usr/include/stdlib.h:766: note: candidates are: int abs(int)
/usr/include/c++/4.3/cstdlib:144: note: long int std::abs(long int)
/usr/include/c++/4.3/cstdlib:175: note: long long int __gnu_cxx::abs(long long int)
/usr/include/c++/4.3/cmath:99: note: double std::abs(double)
/usr/include/c++/4.3/cmath:103: note: float std::abs(float)
/usr/include/c++/4.3/cmath:107: note: long double std::abs(long double)
I can create my own function
float MyAbs(float f){
return sqrt(f * f);
}
std::transform(test.begin(), test.end(), absTest.begin(), MyAbs);
And everything works. The reference on cplusplus.com says that the fourth input can be an UnaryOperation defined by:
Unary function that accepts one element of the type pointed to by InputIterator as argument, and returns some result value convertible to the type pointed to by OutputIterator.
This can either be a function pointer or a function object.
To me this should be able to use std::abs(). I also tried fabs with the same result. What am I missing?
std::abs is an overloaded function, not a template function. When obtaining a pointer to the function, you can choose a specific overload by casting:
std::transform(test.begin(), test.end(), absTest.begin(),
static_cast<float (*)(float)>(&std::abs));
or by using a function pointer variable:
float (*fabs)(float) = &std::abs;
std::transform(test.begin(), test.end(), absTest.begin(), fabs);
Note that I also removed the () you put after abs, since this is a function and not a class that needs to be instantiated.
std::abs is not a template. Any function in headers prefixed with a c like cmath or cstdlib do not have any C++ features like templates, because they represent the C standard library.
Also std::abs is for integral types. You should be using std::fabs for floating point types.
I dont like function pointer casts, so in cases like this one, i usually write some wrappers like these:
namespace hlp {
template <class T> struct iabs {
static_assert(std::is_integral<T>::value, "");
T operator()(T const& t){ return std::abs(t); }
};
template <class T> struct fabs {
static_assert(std::is_floating_point<T>::value, "");
T operator()(T const& t){ return std::fabs(t); }
};
}
You can use those wrappers like you wanted to use std::abs in your question.
The static_assert will generate a clean compiler error when you try to use the integral version for floating point types or vice versa.
#include <iostream>
using namespace std;
template <typename T>
T max(T x, T y)
{
return (x > y) ? x : y;
}
int main()
{
cout << max(3, 7) << std::endl;
cout << max(3.0, 7.0) << std::endl;
cout << max(3, 7.0) << std::endl;
return 0;
}
I'm Expecting max's Instance here
cout << max(3, 7) << std::endl; // max (int, int)
cout << max(3.0, 7.0) << std::endl; // max (double, double)
cout << max(3, 7.0) << std::endl; // max(int, double)
Then what is the problem ? Why I'm getting
11 25 [Error] call of overloaded 'max(double, double)' is ambiguous
If you view the compile error in full, you'd see why. Here's what gcc 5.2 gives me:
main.cpp: In function 'int main()':
main.cpp:10:21: error: call of overloaded 'max(int, int)' is ambiguous
cout << max(3, 7) << std::endl;
^
main.cpp:4:3: note: candidate: T max(T, T) [with T = int]
T max(T x, T y)
^
In file included from /usr/local/include/c++/5.2.0/bits/char_traits.h:39:0,
from /usr/local/include/c++/5.2.0/ios:40,
from /usr/local/include/c++/5.2.0/ostream:38,
from /usr/local/include/c++/5.2.0/iostream:39,
from main.cpp:1:
/usr/local/include/c++/5.2.0/bits/stl_algobase.h:219:5: note: candidate: constexpr const _Tp& std::max(const _Tp&, const _Tp&) [with _Tp = int]
max(const _Tp& __a, const _Tp& __b)
^
Basically, there are two max functions - yours and std::max, which is included by some chain of other #includes from <iostream>. The latter is found by lookup because of your
using namespace std;
Effectively, we have:
template <typename T> T max(T, T); // yours
template <typename T> T const& max(T const&, T const&); // std
Neither is better than the other, hence ambiguous. This is a great reason to avoid using namespace std. Or a great reason to not reinvent the wheel when it comes to standard library functions - just use std::max. Or both.
On the other hand, this one
max(3, 7.0)
will fail regardless as a template deduction failure. It would deduce T as int for the first argument, and T as double for the second - but there can only be one T! You would have to explicitly call either max<int>(3, 7.0) or max<double>(3, 7.0) to get around the deduction failure, depending on which of the two arguments you want to cast.
The line
using namespace std;
makes things complicated, for sure. However, even after you remove that line, the problem continues to exist.
The call max(3, 7.0) can be resolved to max<int> or max<double>. To resolve to max<int> a double has to be converted to an int. To resolve to max<double>, an int has to be converted to a double. Since both require a conversion and one conversion cannot be given higher priority than the other, the compiler is not able to resolve which one to use.
You'll have to be explicit which version of max you want to use.
max<int>(3, 7.0) will convert 7.0, a double, to an int.
max<double>(3, 7.0) will convert 3, an int, to a double.
Max is a library function.just change the max identifier for your function to max1 or any other name that is not a function defined any header files.
That should solve your problem.
In c++14, std::result_of is supposed to result in SFINAE if the expression is ill-formed*. Instead I'm getting a compilation error ("invalid operands to binary expression") on my final case below (i.e. letting the compiler deduce type for std::plus<>). The first three cases work as expected. Code and results shown below.
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/apply.hpp>
#include <iostream>
#include <utility>
#include <stdexcept>
#include <functional>
namespace mpl = boost::mpl;
template <typename OP, typename T, typename OP_T = typename mpl::apply<OP, T>::type>
struct apply_if_ok: OP_T {
template <typename...Args, typename R = std::result_of_t<OP_T(Args...)>>
R operator()(Args&&...args) const {
return static_cast<OP_T>(*this)(std::forward<Args>(args)...);
}
template <typename...Args>
auto operator()(...) const {
// throw std::runtime_error("Invalid arguments");
return "Invalid arguments";
}
};
int main() {
using OP = std::plus<mpl::_>;
int i = 3;
auto n1 = apply_if_ok<OP, void>()(1, 2);
std::cout << "plus (1, 2) = " << n1 << std::endl;
auto n2 = apply_if_ok<OP, void>()(1, &i);
std::cout << "plus (1, *) = " << n2 << std::endl;
auto n3 = apply_if_ok<OP, int>()(&i, &i);
std::cout << "plus (*, *) = " << n3 << std::endl;
// auto n4 = apply_if_ok<OP, void>()(&i, &i);
// std::cout << "plus (*, *) = " << n4 << std::endl;
}
The output:
% c++ -std=c++1y -g -pedantic sfinae_result_of.cc -o sfinae_result_of
./sfinae_result_of
plus (1, 2) = 3
plus (1, *) = 0x7fff5e782a80
plus (*, *) = Invalid arguments
% c++ -v
Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin14.1.0
Thread model: posix
Any pointers on what I'm doing wrong would be appreciated!
Thanks.
From cppreference.com. I think relevant standard reference is 20.10.7.6, comments on last table entry.
This is caused by a bug in libc++, which I actually just reported a few days ago. (Update: The bug has been fixed in trunk.)
The problem is that their "diamond functor" implementation is non-conforming. For instance, they implemented std::plus<void>::operator() as follows:
template <class _T1, class _T2>
_LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
auto operator()(_T1&& __t, _T2&& __u) const
{ return _VSTD::forward<_T1>(__t) + _VSTD::forward<_T2>(__u); }
when it should be
template <class _T1, class _T2>
_LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
auto operator()(_T1&& __t, _T2&& __u) const
-> decltype(_VSTD::forward<_T1>(__t) + _VSTD::forward<_T2>(__u))
{ return _VSTD::forward<_T1>(__t) + _VSTD::forward<_T2>(__u); }
The missing trailing-return-type means two things:
They are no longer "perfectly returning"; instead, the return type is deduced using the rules for auto, essentially causing it to be decayed. The trailing return type, when the expression in it is well-formed, is equivalent to returning decltype(auto).
SFINAE no longer applies to the expression _VSTD::forward<_T1>(__t) + _VSTD::forward<_T2>(__u). In a bug-free implementation, the operator() declaration would be removed from the overload set, overload resolution will fail, and std::result_of will then do its SFINAE-friendly magic. Instead, the function declaration is successfully instantiated, selected by overload resolution, and then a hard error occurs when the compiler attempts to instantiate the body to actually deduce the return type.
Your problem is caused by #2.
All I'm trying to do is implement the equal algorithm. However, when I test with a few strings, I get an ambiguity error. I think the compiler cannot differentiate between the A and the B. Why is this?
template <class A, class B> bool equal(A beg, A end, B out)
{
while(beg != end) {
if(*beg == *out) {
++beg;
++out;
}
else return false;
}
return true;
}
MAIN
std::string a("This is a string");
std::string b("This is a string");
std::string c("String c");
std::cout << "a and b are " << equal(a.begin(), a.end(), b.begin()) << std::endl;
std::cout << "a and c are " << equal(a.begin(), a.end(), c.begin()) << std::endl;
ERROR MESSAGE
procedures_main.cpp:17:35: error: call to 'equal' is ambiguous
std::cout << "a and b is " << equal(a.begin(), a.end(), b.begin()) << std::endl;
^~~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/algorithm:1105:1: note:
candidate function [with _InputIterator1 = std::__1::__wrap_iter<char *>, _InputIterator2 =
std::__1::__wrap_iter<char *>]
equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2)
^
./procedures.hpp:73:34: note: candidate function [with A = std::__1::__wrap_iter<char *>, B = std::__1::__wrap_iter<char
*>]
template <class A, class B> bool equal(A beg, A end, B out)
The problem is that the arguments (the iterators from std::string) are in the namespace std and in this namespace, there is another algorithm called equal which is a candidate due to argument dependent lookup (ADL). You need to explicitly qualify your algorithm:
std::cout << "a and b are " << ::equal(a.begin(), a.end(), b.begin()) << std::endl;
// ^^ here
Note that the C++ standard does not require the iterators to be a type in std, but is allows it and you compiler/standard library decided to use this option.
This is the result of the so-called Argument-Dependent Name Lookup. There is standard algorithm std::equal in C++. The compiler sees that arguments of your function call belong to namespace std. So it also takes into consideration any function with name equal in namespace std. As the result it finds two functions: the one that is defined by you and the other that is declared in namespace std.
To escape the error use fully qualified name of your function that is ::equal.
By the way you use your function incorrectly and such a usage has undefined behaviour. The second range must have at least the same size as the first range. In your example wnen you use strings a and c the size of c is less than size of a.