I am trying to do some practice with function templates as in the following example:
#include <iostream>
using namespace std;
template <class T>
T max(T a, T b)
{
return a > b ? a : b;
}
int main()
{
cout << "max(10, 15) = " << max(10, 15) << endl;
retun 0;
}
But I got the following errors. Could anybody recognize where the problem is?
..\src\main.cpp:59:40: error: call of overloaded 'max(int, int)' is
ambiguous
cout << "max(10, 15) = " << max(10, 15) << endl;
^
..\src\main.cpp:16:3: note: candidate: 'T max(T, T) [with T = int]'
T max(T a, T b)
^~~
In file included from c:\mingw\include\c++\8.1.0\bits\char_traits.h:39,
from c:\mingw\include\c++\8.1.0\ios:40,
from c:\mingw\include\c++\8.1.0\ostream:38,
from c:\mingw\include\c++\8.1.0\iostream:39,
from ..\src\main.cpp:9:
c:\mingw\include\c++\8.1.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)
I am sorry I am new to templates. Thanks for your help.
Your usage of templates is correct, but the compiler complains that there already is a function called max with same arguments.
It's full name would be std::max, but because you wrote using namespace std its just max and compiler cannot know which function to call.
Solution is not to use using, see Why is "using namespace std" considered bad practice? .
using namespace std; is the issue
Please stop using that, see why
The iostream header includes another header file that pulls std::max, giving a compiler error.
Related
The following test program reproduces compilation errors within the context of a larger program:
#include <algorithm>
#include <iostream>
#include <vector>
using std::for_each;
using std::vector;
using std::cout;
using std::endl;
template<typename T, typename C = vector<T>>
class display_container{
public:
display_container(const C& cr):this->cr(cr){this->();}
~display_container(){}
private:
constexpr void operator () (void){if(cr.empty()){cout << "NULL" << " ";} else{for_each(cr.begin(), cr.end(), [](const T& crt){cout << crt << " ";});}}
const C& cr;
};
int main (void){
int n = 5;
vector<int> vec(n, 0);
display_container d(vec);
cout << endl;
return 0;
}
The following is a log of the compiler errors:
g++ -ggdb -std=c++17 -Wall -Werror=pedantic -Wextra -c code.cpp
code.cpp: In constructor ‘display_container<T, C>::display_container(const C&)’:
code.cpp:12:40: error: expected identifier before ‘this’
display_container(const C& cr):this->cr(cr){this->();}
^~~~
code.cpp:12:40: error: expected ‘{’ before ‘this’
code.cpp: In function ‘int main()’:
code.cpp:23:28: error: class template argument deduction failed:
display_container d(vec);
^
code.cpp:23:28: error: no matching function for call to ‘display_container(std::vector<int>&)’
code.cpp:12:9: note: candidate: template<class T, class C> display_container(const C&)-> display_container<T, C>
display_container(const C& cr):this->cr(cr){this->();}
^~~~~~~~~~~~~~~~~
code.cpp:12:9: note: template argument deduction/substitution failed:
code.cpp:23:28: note: couldn't deduce template parameter ‘T’
display_container d(vec);
^
code.cpp:10:7: note: candidate: template<class T, class C> display_container(display_container<T, C>)-> display_container<T, C>
class display_container{
^~~~~~~~~~~~~~~~~
code.cpp:10:7: note: template argument deduction/substitution failed:
code.cpp:23:28: note: ‘std::vector<int>’ is not derived from ‘display_container<T, C>’
display_container d(vec);
^
make: *** [makefile:20: code.o] Error 1
I presume that the remaining errors trickle down from the first error related to the inline constructor definition for the display_container template class.
Any suggestions on what is wrong with the code related to inline constructor definition?
TIA
The compiler can not fetch the template type of vector yet:
#include <algorithm>
#include <iostream>
#include <vector>
using std::for_each;
using std::vector;
using std::cout;
using std::endl;
template<typename T, typename C = vector<T>>
class display_container{
public:
display_container(const C& cr): cr(cr) { (*this)(); }
~display_container(){}
private:
constexpr void operator () (void){if(cr.empty()){cout << "NULL" << " ";} else{for_each(cr.begin(), cr.end(), [](const T& crt){cout << crt << " ";});}}
const C& cr;
};
int main (void){
int n = 5;
vector<int> vec(n, 0);
display_container<int> d(vec);
cout << endl;
return 0;
}
You couldn't (and don't need) qualify data members in member initializer list by this, they're expected to be the identifier. The correct syntax should be
display_container(const C& cr):cr(cr){(*this)();}
You should dereference on this and then call operator() on it (as showed abolve), or you can call operator() explicitly like this->operator()(); (which looks ugly).
You should specify the template argument for display_container.
display_container<int> d(vec);
LIVE
#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.
I'm reading boost's config/suffix.hpp, and I'm surprised with the following code:
// Workaround for the unfortunate min/max macros defined by some platform headers
#define BOOST_PREVENT_MACRO_SUBSTITUTION
// <skipped unimportant lines>
namespace std {
template <class _Tp>
inline const _Tp& min BOOST_PREVENT_MACRO_SUBSTITUTION (const _Tp& __a, const _Tp& __b) {
return __b < __a ? __b : __a;
}
template <class _Tp>
inline const _Tp& max BOOST_PREVENT_MACRO_SUBSTITUTION (const _Tp& __a, const _Tp& __b) {
return __a < __b ? __b : __a;
}
}
This actually seems to be a valid thing to make the definitions of min and max functions compile when the same-named macros are defined. But why would this be useful at the actual call site? Wouldn't the macro actually substitute when the functions are called? I've tried to make a simple test, "emulating" this setup:
#include <iostream>
#define PREVENT_MACRO_SUBSTITUTION
#define max(x,y) ((x)<(y)?(y):(x))
namespace test
{
int max PREVENT_MACRO_SUBSTITUTION (int a, int b)
{
std::cerr << "Function max\n";
return a<b?b:a;
}
}
int main()
{
int x=test::max(5,6);
std::cout << "x="<<x<<"\n";
}
And, as expected, I get a compilation error due to expansion of max macro. So, how is boost's macro substitution prevention supposed to work?
It's not supposed to do what you think it's supposed to do.
If a min or max macro is defined, and the user wishes to call those std::min or std::max functions, it's the user's responsibility to make sure the macro is suppressed. Possibly again using BOOST_PREVENT_MACRO_SUBSTITUTION, possibly using parentheses ((std::min) (...)).
All the use of BOOST_PREVENT_MACRO_SUBSTITUTION is doing here is preventing a syntax error from being raised for the definition of std::min and std::max, like you figured out already. It would happily expand min as a macro if the header had used inline const _Tp& min (const _Tp& __a, const _Tp& __b), resulting in something like inline const _Tp& ((const _Tp& __a) < (const _Tp& __b) ? (const _Tp& __a) : (const _Tp& __b)). But if code doesn't actually use min or max, then including that header file should be harmless.
I can't figure out what is ambiguous about swap(arr[i++],arr[n--]); below. Please educate me on my wrongful ways.
#include <iostream>
#include <string>
template <typename T> void swap ( T & a, T & b )
{
T temp = b;
b = a;
a = temp;
}
template <typename T> void reverse_array ( T * arr, size_t n )
{
size_t i = 0;
while (i < n) swap(arr[i++],arr[n--]); // problem line
}
int main ()
{
char mystr [] = "Obama smokes";
reverse_array(mystr, sizeof(mystr)/sizeof(char));
return 0;
}
codepad has an implicit using namespace std;, which is a really bad idea and makes your swap conflict with std::swap. You can use ::swap instead, but not before fixing your bounds problem by passing sizeof mystr - 2 instead of sizeof(mystr)/sizeof(char).
As #minitech mentions in his answer, the problem is because of the implicit namespace declaration, e.g. using namespace std;
With that I get the following error, which shows that the conflict is with std::swap:
100%] Building CXX object CMakeFiles/csi_projects.dir/main.cpp.o
/home/vsnyc/ClionProjects/main.cpp: In instantiation of ‘void reverse_array(T*, size_t) [with T = char; size_t = long unsigned int]’:
/home/vsnyc/ClionProjects/main.cpp:151:52: required from here
/home/vsnyc/ClionProjects/main.cpp:144:43: error: call of overloaded ‘swap(char&, char&)’ is ambiguous
while (i < n) { swap(arr[i++],arr[n--]); } // problem line
^
/home/vsnyc/ClionProjects/main.cpp:144:43: note: candidates are:
/home/vsnyc/ClionProjects/main.cpp:134:28: note: void swap(T&, T&) [with T = char]
template <typename T> void swap ( T & a, T & b )
^
In file included from /usr/include/c++/4.8/bits/stl_pair.h:59:0,
from /usr/include/c++/4.8/bits/stl_algobase.h:64,
from /usr/include/c++/4.8/bits/char_traits.h:39,
from /usr/include/c++/4.8/ios:40,
from /usr/include/c++/4.8/ostream:38,
from /usr/include/c++/4.8/iostream:39,
from /home/vsnyc/ClionProjects/main.cpp:1:
/usr/include/c++/4.8/bits/move.h:166:5: note: void std::swap(_Tp&, _Tp&) [with _Tp = char]
swap(_Tp& __a, _Tp& __b)
^
Can anyone tell me the cause of error ?
Error is
C:\web\template1.cpp||In function 'int main()':|
C:\web\template1.cpp|23|error: call of overloaded 'swap(int&, int&)' is ambiguous|
C:\web\template1.cpp|6|note: candidates are: void swap(X&, X&) [with X = int]|
c:\program files\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\bits\move.h|76|note: void std::swap(_Tp&, _Tp&) [with _Tp = int]|
C:\web\template1.cpp|24|error: call of overloaded 'swap(double&, double&)' is ambiguous|
C:\web\template1.cpp|6|note: candidates are: void swap(X&, X&) [with X = double]|
c:\program files\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\bits\move.h|76|note: void std::swap(_Tp&, _Tp&) [with _Tp = double]|
C:\web\template1.cpp|25|error: call of overloaded 'swap(char&, char&)' is ambiguous|
C:\web\template1.cpp|6|note: candidates are: void swap(X&, X&) [with X = char]|
c:\program files\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\bits\move.h|76|note: void std::swap(_Tp&, _Tp&) [with _Tp = char]|
||=== Build finished: 3 errors, 0 warnings ===|
#include <iostream>
using namespace std;
template <typename X>
void swap(X &a, X &b)
{
X temp = a;
a = b;
b = temp;
}
int main()
{
int i=10, j=20;
double x=10.1, y=23.3;
char a='x', b='z';
cout<<"i="<<i<<"\tj="<<j<<endl;
cout<<"x="<<x<<"\ty="<<y<<endl;
cout<<"a="<<a<<"\tb="<<b<<endl;
swap(i,j);
swap(x,y);
swap(a,b);
cout<<"i="<<i<<"\tj="<<j<<endl;
cout<<"x="<<x<<"\ty="<<y<<endl;
cout<<"a="<<a<<"\tb="<<b<<endl;
return 0;
}
Your swap conflicts with std::swap. Remove using namespace std; above and correct the rest code from std namespace.
std::cout<<"i="<<i<<"\tj="<<j<<std::endl;
std::cout<<"x="<<x<<"\ty="<<y<<std::endl;
std::cout<<"a="<<a<<"\tb="<<b<<std::endl;
Also it's worth reading Why is "using namespace std" considered bad practice?
Rename swap() as swap2() or the like. Or, better, never issue using namespace std;.
As written, your code introduces std::swap() through iostream, then dumps it atop your own swap() by using namespace.
There is already a swap function declared somewhere in your code. Change the function's name or remove the declaration of the other swap function.
This ambiguous errors occur due to using std functions as general functions.
There are two ways to overcome this.
1) Instead of declaring using namespace std; use std::cout
whenever you need to print any and std::endl for new line.
#include <iostream>
template <typename X>
void swap(X &a, X &b)
{
X temp = a;
a = b;
b = temp;
}
int main()
{
int i=10, j=20;
double x=10.1, y=23.3;
char a='x', b='z';
std::cout<<"i="<<i<<"\tj="<<j<<std::endl;
std::cout<<"x="<<x<<"\ty="<<y<<std::endl;
std::cout<<"a="<<a<<"\tb="<<b<<std::endl;
swap(i,j);
swap(x,y);
swap(a,b);
std::cout<<"i="<<i<<"\tj="<<j<<std::endl;
std::cout<<"x="<<x<<"\ty="<<y<<std::endl;
std::cout<<"a="<<a<<"\tb="<<b<<std::endl;
return 0;
}
2) You can also change the swap to Swap to not conflict with the inbuilt std::swap function.
#include <iostream>
using namespace std;
template <typename X>
void Swap(X &a, X &b)
{
X temp = a;
a = b;
b = temp;
}
int main()
{
int i=10, j=20;
double x=10.1, y=23.3;
char a='x', b='z';
cout<<"i="<<i<<"\tj="<<j<<endl;
cout<<"x="<<x<<"\ty="<<y<<endl;
cout<<"a="<<a<<"\tb="<<b<<endl;
Swap(i,j);
Swap(x,y);
Swap(a,b);
cout<<"i="<<i<<"\tj="<<j<<endl;
cout<<"x="<<x<<"\ty="<<y<<endl;
cout<<"a="<<a<<"\tb="<<b<<endl;
return 0;
}