I’ve been playing around with type deduction/printing using templates with code of the form:
#include <iostream>
template <typename T>
class printType {};
template <typename T>
std::ostream& operator<<(std::ostream& os, const printType<T>&)
{
os << "SomeType"; return os;
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const printType<T*>&)
{
os << printType<T>() << "*"; return os;
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const printType<T&>&)
{
os << printType<T>() << "&"; return os;
}
// etc... and can call on a variable through
template <typename T>
printType<T> print(T) { return printType<T>(); }
int main()
{
int a = 7;
int *p = &a;
int &r = a;
//OK: return SomeType*
std::cout << "type of p: " << print(p) << std::endl;
//Hmmmm: returns SomeType <- (no &: can I get around this?)
std::cout << "type of r: " << print(r) << std::endl;
}
I am wondering whether or not I can get the last line to return int& , that is, either:
(i) have the function template print deduce the type of it’s argument as int& or somehow work out it should return a printType<T&> when I pass it r; or
(ii)whether this is unavoidable because of the way the variable is passed to the function.
Are there any ways around this by changing the form of print or using some other template trickery? If solutions exists, I’d prefer non-C++0x, but is always good to see what short cuts will, if not already, be available in the future.
There is no way to work this around. An expression
p, wherepnames a reference, always has the type the reference refers to. No expression ever has typeT&. So you cannot detect whether an expression originated from a reference or not.This cannot be done with C++0x either. It’s a deep principle of C++ that there are no expressions that have reference type. You can write
decltype(r)to get the type of whatrnames instead of what type the expressionrhas. But you will not be able to writeprint(r), unlessprintis a macro of course, but I don’t see why you would go that horrible road.