Template parameter a pointer?
Hey,
I've been playing around with some templated stuff - a Serialiser similar to the one which is used in Enginuity I think. Normal types serialise properly, but I can't figure out a nice implementation for pointers.
In particular, I have the SerialOp(T& object) templated function. Is there an easy way to determine at runtime whether the object is a pointer, without using RTTI? I was thinking of casting the object to a void*, and seeing if that wasn't 0, but I'm not so sure that it would fail for some objects, and can't find information on trying to cast ints to pointers or whatnot.
Anywho, best case, would there be any way to exclude pointers from the generated template types [I'm guessing no], and secondly, is there any way to determine quickly and easily if a type is a pointer - would the void* cast work?
//end rant
CJM
The void* cast wont work. It will give you a compile-time error if the type isn't a pointer (using static_cast, however a C-style cast will let you do the cast with builtin types giving you some funky void* pointer), but that's the opposite of what you'd need to exclude pointers from being used as the template parameter.
I'm fairly sure you can't have code that does something like
if(isPointer) {...}
else {...}
so your only option would to be create a scenario that would force a compile-time error if the type is a pointer. To do this check out the boost::concept_check library.
I'm fairly sure you can't have code that does something like
if(isPointer) {...}
else {...}
so your only option would to be create a scenario that would force a compile-time error if the type is a pointer. To do this check out the boost::concept_check library.
Actually, just thought of something.
Works with gcc3.2.
template<typename I>void func(I test) { std::cout << "A normal type!" << std::endl;}template<typename I>void func(I* test) { std::cout << "A pointer type!" << std::endl;}int main() { int i=1; int *p=&i; func(i); func(p); return 0;}
Works with gcc3.2.
joanusdmentia,
I'm checking out the Concept Check Library thing you sent to me. I've already tried something like what you describe, but the problem with your second bit of code is that you've got pass by value. I'm using references to get the data into the function, and I'm relatively sure that pointer-to-reference isn't legal. Do you think that the easiest solution would just be then to use T* and T** and then dereference, which is basically equivelent?
CJM
I'm checking out the Concept Check Library thing you sent to me. I've already tried something like what you describe, but the problem with your second bit of code is that you've got pass by value. I'm using references to get the data into the function, and I'm relatively sure that pointer-to-reference isn't legal. Do you think that the easiest solution would just be then to use T* and T** and then dereference, which is basically equivelent?
CJM
There is an alternative, its called type traits, boost has a type traits package:
compiler needs partial specialization support which VC++ 6.0 doesn't have.
notice i've used a constant reference, you should do the same
template < typename T >struct is_pointer { enum { val = false };};template < typename T >struct is_pointer<T*> { enum { val = true };};template < typename T >void SerialOp(const T& obj) { if(is_pointer<T>::val) { /* code to handle pointers */ } else { /* normal code */ }}
compiler needs partial specialization support which VC++ 6.0 doesn't have.
notice i've used a constant reference, you should do the same
Hey snk_kid,
I think that's about as clean as it's gonna get. Thanks.
also, thanks joanusdmentia.
CJM
I think that's about as clean as it's gonna get. Thanks.
also, thanks joanusdmentia.
CJM
Quote:Original post by CJM
I'm using references to get the data into the function, and I'm relatively sure that pointer-to-reference isn't legal. Do you think that the easiest solution would just be then to use T* and T** and then dereference, which is basically equivelent?
CJM
Doesn't matter.
template<typename I>void func(const I& test) { std::cout << "A normal type!" << std::endl;}template<typename I>void func(I* test) { std::cout << "A pointer type!" << std::endl;}
But as snk_kid said, type traits would be better still. (can't believe I didn't think of that!)
And, to avoid generating unnecessary code (since T can't be both pointer type and normal type), you can do this:
This will only instantiate the code that actually gets executed.
template<bool> struct switch_t { };template<class T, bool B>void serialise(const T& a, switch_t<B>) { std::cout << "A normal type!" << std::endl; }template<class T>void serialise(const T& a, switch_t<true>) { std::cout << "A pointer type!" << std::endl; }template<class T>void SerialOp(const T& test) { serialise(test, switch_t<is_pointer<T>::val>()); }
This will only instantiate the code that actually gets executed.
Quote:Original post by roller
And, to avoid generating unnecessary code (since T can't be both pointer type and normal type), you can do this:
*** Source Snippet Removed ***
This will only instantiate the code that actually gets executed.
while i totally agree that this is a better method, the version i posted the if statement is trivially true or false at compile time thus if optimizations (maybe even then) are turned on i'm sure the compiler can easily eliminate the if statement using dead code elimination.
Quote:Original post by snk_kid
< snip >
compiler needs partial specialization support which VC++ 6.0 doesn't have.
notice i've used a constant reference, you should do the same
Hello,
Maybe this should do the trick (and it does not require partial specialisation AFAIK)
template <typename T> struct is_pointer{ static inline bool is(T*) {return true;} static inline bool is(const T&) {return false;}};int _tmain(int argc, _TCHAR* argv[]){ int *pi=0; int i=0; if (is_pointer<int>::is(i)) { std::cout << "i is a pointer" << std::endl; } else { std::cout << "i is NOT a pointer" << std::endl; } if (is_pointer<int>::is(pi)) { std::cout << "pi is a pointer" << std::endl; } else { std::cout << "pi is NOT a pointer" << std::endl; } std::cin >> i; return 0;}
Both VC6 and VC .NET 2003 release mode optimize out the not needed code.
(edit: added VC6 italic stuff ^_^ (this "i logout you while you are editing you post" is rather strange :/ Not sure it is by design...)
Regards,
[Edited by - Emmanuel Deloget on September 28, 2004 9:05:51 AM]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement