C++ templates facing overload mismatch issue. What is wrong in the code? - c++

#include <iostream>
using namespace std;
template<class T>
inline void swap(T &i,T &j)
{
T temp = i;
i=j;
j=temp;
}
int main ()
{
int a = 2,b =5;
swap(a,b);
cout << "a=" <<a<< " b=" <<b<<endl;
return 0;
}
This is a simple swap program using templates. I am new to templates and wanted to learn how to use it.

using namespace std is the problem. There is an std::swap() function that is causing the function call to become ambiguous.

Related

Why is there an ambiguous call for templatized function?

I have a problem with creating a template in c++. I am using xcode for mac.
When passing an int to a swap function I get the error code "ambiguous call". However, passing strings works fine. Why is that?
This is my code
#include <iostream>
#include <cmath>
using namespace std;
template <typename T>
void swap(T& c, T& d)
{
T temp = c;
c = d;
d = temp;
}
int main()
{
int a = 10;
int b = 20;
swap(a, b); // this is an error "ambiguous call"
cout << a << "\t" << b;
string first_name = "Bob";
string last_name = "Hoskins";
swap(first_name, last_name); // this works
cout << first_name << "\t" << last_name;
return 0;
}
You have using namespace std; which brings std::swap into scope. This means the template swap that you have written conflicts with std::swap, and you get an ambiguous call when you pass it 2 ints.
Takeaway: Never do using namespace std;
The interesting part is that calling swap with 2 std::strings works. That's because there is a specialization of std::swap for std::string. The specialization is considered a better match, and so it's called instead of your own swap.

Storing a vector of various void function pointers with its parameters

I'm looking for a way to store function pointers in a container like a vector. This is possible if all the functions have the same parameters but can I do if the functions have individually unique parameters?
#include <iostream>
#include <vector>
using namespace std;
void sayHi() {
cout << "Hi" << endl;
}
void sayNum(int num) {
cout << num << endl;
}
int main() {
vector<void(*)()> funcs; // vector of 0 argument functions
funcs.push_back(sayHi);
funcs.push_back(sayNum); // can't store sayNum because it takes arguments
}
Note that I can't use std::function or std::bind because VS2013 doesn't have them and I'd rather not use the boost library. The solution must be allow the possibility to iterate through the vector of function pointers and execute each one with some valid arguments.
Forgive my potential ignorance about how function pointers work, I'm very used to doing this sort of thing in Javascript in one statement :P
Made the mistake of not including as I couldn't see it mentioned in anybody's code examples but it's probably just me being bad at C++.
Not going to accept my own answer, but thought I'd post my code just in the interests of anybody who might find it useful.
#include <iostream>
#include <vector>
#include <functional>
using namespace std;
typedef std::vector<std::function<void(void)>> f_list;
f_list f1;
void _sayHi();
void _sayNum(int num);
void sayHi() {
f1.push_back(
std::bind(&_sayHi)
);
}
void sayNum(int num) {
f1.push_back(
std::bind(&_sayNum, num)
);
}
void _sayHi() {
cout << "hi" << endl;
}
void _sayNum(int num) {
cout << num << endl;
}
int main() {
sayHi();
sayNum(5);
for (int i = 0; i < f1.size(); i++) {
f1.at(i)(); // will execute desired functions
}
}
VS 2103 has std::function, std::bind and lambdas. Simply use them.

Redeclaring a function inside a function

I stumbled across a strange c++ snippet. I consider this as bad code. Why would someone repeat the function declaration inside a function? It even compiles when changing the type signature to unsigned int sum(int, int) producing the expected result 4294967294j. Why does this even compile?
#include <iostream>
#include <typeinfo>
using namespace std;
int sum(int a, int b){
return a + b;
}
int main()
{
int sum(int, int); // redeclaring sum???
int a = -1;
auto result = sum(a, a);
cout << result << typeid(result).name() << endl;
}
Edit: It compiles for me... but is it valid C++ code? If not why does the compiler (mingw 4.8.1) allow it?
Sometimes there is a sense to redeclare a function inside a block scope. For example if you want to set a default argument. Consider the following code
#include <typeinfo>
using namespace std;
int sum(int a, int b){
return a + b;
}
int main()
{
int sum(int, int = -1 ); // redeclaring sum???
int a = -1;
auto result = sum(a, a);
cout << result << typeid(result).name() << endl;
result = sum(a);
cout << result << typeid(result).name() << endl;
}
Another case is when you want to call a concrete function from a set of overloaded functions. Consider the following example
#include <iostream>
void g( int ) { std::cout << "g( int )" << std::endl; }
void g( short ) { std::cout << "g( short )" << std::endl; }
int main()
{
char c = 'c';
g( c );
{
void g( short );
g( c );
}
}
If that's the actual code, there's no reason to do it.
If the function sum is defined somewhere else though, the declaration inside main makes it accessible only inside main. You can't use it anywhere else in that translation unit (unless of course you declare it). So it's a sort of limiting visibility to where it's needed, but, granted, it's not very readable.
Regarding changing the return type - that's illegal. You're not seeing any issues with unsigned int, but if you try
char sum(int, int); // redeclaring sum???
you'll see there's a problem there.

Cout and endl errors

I have listed my code below. I get soooo many errors saying cout and endl was not declared in this scope. I do not know what I am doing wrong or how to force the class to recognise cout? I hope I am explaining my problem correctly. If I comment out the methods (not the constructor) it works. I am probably just making a novice mistake here - please help.
using namespace std;
class SignatureDemo{
public:
SignatureDemo (int val):m_Val(val){}
void demo(int n){
cout<<++m_Val<<"\tdemo(int)"<<endl;
}
void demo(int n)const{
cout<<m_Val<<"\tdemo(int) const"<<endl;
}
void demo(short s){
cout<<++m_Val<<"\tdemo(short)"<<endl;
}
void demo(float f){
cout<<++m_Val<<"\tdemo(float)"<<endl;
}
void demo(float f) const{
cout<<m_Val<<"\tdemo(float) const"<<endl;
}
void demo(double d){
cout<<++m_Val<<"\tdemo(double)"<<endl;
}
private:
int m_Val;
};
int main()
{
SignatureDemo sd(5);
return 0;
}
The compiler needs to know where to find std::cout first. You just need to include the correct header file:
#include <iostream>
I'd suggest you not to pollute the namespace using using directives. Instead either learn to prefix std classes/objects with std:: or use specific using directives:
using std::cout;
using std::endl;

Passing a template func. as a func. ptr to an overloaded func. - is there a way to compile this code?

Just a general c++ curiosity:
This code below shouldn't compile because it's impossible to know which to instantiate: temp(const int&) or temp(const string&) when calling func(temp) - this part i know.
What i would like to know is if there is anything i can do to the line marked PASSINGLINE to get the compiler to deduce that i want FPTR1 called and not FPTR2 ?
#include<iostream>
using std::cout;
using std::endl;
/*FPTR1*/ void func(void(*fptr)(const int&)){ fptr(1001001);}
/*FPTR2*/ void func(void(*fptr)(const string&)){ fptr("1001001"); }
template <typename T>
void temp(const T &t){ cout << t << endl; }
int main(){
/*PASSINGLINE*/ func(temp);
return 0;
}
Thank you.
You can use a static_cast:
func (static_cast <void(*)(const int&)> (&temp));
Tested with GCC 4.x.
func(temp<int>);
There's no way to make the compiler infer the template argument, that is more succinct or clearer than just explicitly specifying it, in this case.
Edit: The following code compiles without warning and produces the expected result:
#include<iostream>
#include<string>
using std::string;
using std::cout;
using std::endl;
/*FPTR1*/ void func(void(*fptr)(const int&)){ fptr(1001001);}
/*FPTR2*/ void func(void(*fptr)(const string&)){ fptr("1001001"); }
template <typename T>
void temp(const T &t){ cout << t << endl; }
int main(){
/*PASSINGLINE*/ func(temp<int>);
return 0;
}