Library and Template Trouble
Hi all,
I am trying to implement a generic smart pointer library which links to another main program. To make the smart pointer library generic I am using a template with a typename called "type". However, when I attempt to link my library to the main program and compile them both, I get a compiler error which says something like "Expected type, got link" (where "link" is a class in the main program).
I was wondering why this is happening and what I can do to fix it. I've tried passing my smart_pointer an "int" type and this works fine.
For example:
smart_pointer<int> p = new int(); // Works okay!
However...
smart_pointer<link> l = new link(); // Does not work! (Compiler: "Expected type, got link")
I've included my code below (not all of it, but just the parts I think are relevant). Also, I'm not supposed to alter the main program in any way (just my library).
Any help would be greatly appreciated.
Thanks.
EDIT: Please refer to the code on the third post below this one.
Re: Library and Template Trouble
I suppose I'll first give the obligatory "there are perfectly good smart pointer libraries available, why are you reinventing the wheel" response. It looks like this is probably homework, but someone was going to say it so why not me?
That done, it would be most helpful if you gave us the exact error message and indicate the line in your code that generates it. (The line number can sometimes be hard to find in template errors. There will probably be one pointing somewhere in smart_pointer, and one pointing somewhere in main(). Both will be useful.)
Re: Library and Template Trouble
"link" wouldn't happen to actually be a template class by any chance...?
Your code (once stripped of un-useable code) compiles fine, so you are keeping something from us.
Please post the minimal but full and exact code that recreates this. Code tags ([CODE][/CODE]) would be a plus.
Re: Library and Template Trouble
Sorry for my previous inadequacies.
I have stripped down the code to be as small as possible yet still generate the error in question.
So, I have these two files "test.h" (library) and "test_main.c" (main program). When I try to compile these two files using:
Code:
g++ test_main.c -o test_main
I get the following error:
Code:
test_main.c: In function ‘int main(int, char**)’:
test_main.c:14:22: error: type/value mismatch at argument 1 in template parameter list for ‘template<class type> class smart_pointers::smart_pointer’
test_main.c:14:22: error: expected a type, got ‘link’
test_main.c:14:26: error: invalid type in declaration before ‘=’ token
test_main.c:14:32: error: expected type-specifier before ‘link’
test_main.c:14:32: error: invalid conversion from ‘int*’ to ‘int’
test_main.c:14:32: error: expected ‘,’ or ‘;’ before ‘link’
test_main.c:15:5: error: base operand of ‘->’ is not a pointer
test_main.c:16:20: error: base operand of ‘->’ is not a pointer
Why is this happening? When I rename all instances of "link" in test_main.c it compiles fine... But I need the program to work without changing the test_main.c file.
Here is my code:
test.h
Code:
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
namespace smart_pointers{
using namespace std;
template<typename type>
class smart_pointer{
public:
type *pdata;
smart_pointer(){
pdata = NULL;
}
smart_pointer(type *dat){
pdata = dat;
}
type *operator->(){
return pdata;
}
};
}
test_main.c
Code:
#include "test.h"
using namespace smart_pointers;
class link
{
public:
smart_pointer<link>next;
int data;
};
int main(int argc, char*argv[])
{
smart_pointer<link> l = new link();
l->data = 5;
printf("%d\n", l->data);
}
Thank your for your time.
Re: Library and Template Trouble
Quote:
Originally Posted by ace_of_pentacles
Why is this happening? When I rename all instances of "link" in test_main.c it compiles fine... But I need the program to work without changing the test_main.c file.
It sounds like a name collision issue. I tested your code with g++ 4.4.5, and indeed I faced the same problem. Commenting out the #include <iostream> removed the problem. (In the example you really do not need any of the headers; the header you do need is <cstddef> for NULL, and then <cstdio> in test_main.c, which would be better named test_main.cpp.) A better way to handle this would be to use your own namespace, e.g.,:
Code:
namespace aop
{
class link
{
public:
smart_pointer<link>next;
int data;
};
}
int main(int argc, char* argv[])
{
smart_pointer<aop::link> l = new aop::link();
l->data = 5;
printf("%d\n", l->data);
}
By the way, do not use using directives at namespace scope in header files.
Re: Library and Template Trouble
I didn't reproduce the error with using MinGW with your exact code, however, I get the exact same diagnostic with this:
Code:
using namespace std;
template <typename>
class some_template
{
};
namespace std
{int a = 5;}
class a
{
};
int main()
{
some_template<a>;
}
My guess is that somewhere inside the iostream is an object called link (possibly inside namespace std, but I cannot be sure). Both are allowed to coexist (one is a type, the other is an instance). The problem is that the template decided to resolve to the link value, rather than your user supplied link type.
You can solve this by prefixing your link to specify you want the globally defined one:
Code:
using namespace std;
template <typename>
class some_template
{
};
namespace std
{int a = 5;}
class a
{
};
int main()
{
some_template< ::a>; //Watch the space! <:: is a keyword...
}
However... This will only work if the instance "link" was first defined in namespace std.
To add to laserlight's suggestion though, I'd recommend not using "using namespace std" either. The amount of collisions it provides usually isn't worth it (IMO)
Re: Library and Template Trouble
If indeed there is a link object in namespace std, then the solution is to drop the "using namespace std;" line and instead make individual statements like
using std::cout;
using std::endl;
etc.
Re: Library and Template Trouble
Quote:
Originally Posted by
Lindley
If indeed there is a link object in namespace std...
Wouldn't that be a violation of the standard though? Is the implementation allowed to add things to namespace std that is not referenced in the standard and not prefixed by _? Or is it just bad practice?
Re: Library and Template Trouble
Quote:
Originally Posted by Lindley
If indeed there is a link object in namespace std
I did not check, but I think link refers to the function of that name from <unistd.h>, which may have been included in <iostream>. If my guess is correct then link would be in the global namespace. My hunch is based on the fact that when I commented out the using directive for namespace std, my attempted compile still failed.