Re: implicit_cast isn't possible... is it?
* Tom1s:
Given the following:
static_cast<T>( expr )
This will evaluate to an l-value if T is a reference type -- otherwise it
will evaluate to an r-value.
The same goes for reinterpret_cast.
I've been trying to write an "implicit_cast", but I don't think it's
possible to achieve the same behaviour.
For instance, here would be its most basic use:
/* Code Snippet A */
void SomeFunc( signed char ) {}
void SomeFunc( unsigned char ) {}
int main()
{
SomeFunc( implicit_cast<unsigned char>(45) );
}
But then if we simulatenously try to achieve the l-value behaviour, it
won't compile -- giving an ambiguity error. Here's the code I have so
far:
/* Code Snippet B */
template <class U, class T>
inline U implicit_cast(const T& t) { return t; }
template <class U, class T>
inline U implicit_cast(T& t) { return t; }
void SomeFunc(unsigned char) {}
void SomeFunc(signed char) {}
struct Base {
void SomeConstFunction() const {}
};
struct Derived : Base { Derived() {} };
int main()
{
SomeFunc( implicit_cast<unsigned char>(27) );
SomeFunc( implicit_cast<signed char>(27) );
Derived derived;
implicit_cast<Base&>(derived) = Base();
Derived const cderived;
implicit_cast<const Base&>(cderived).SomeConstFunction();
/* The line immediately above results in an ambiguity error */
}
(Initially I thought we'd have the problem of "implicit_cast" creating a
temporary object when its U parameter is a non-reference type, but this
doesn't seem to be a problem because "static_cast" does the same thing,
e.g.:)
/* Code Snippet C */
#include <iostream>
using std::cout;
#include <cstdlib>
struct Base {
void PrintMyAddress() const
{
cout << static_cast<const void*>(this);
/* Here's an instance where I'd use
implicit_cast */
}
};
struct Derived : Base {};
int main()
{
Derived derived;
static_cast<Base>(derived).PrintMyAddress();
cout << '\n';
static_cast<Base&>(derived).PrintMyAddress();
cout << '\n';
std::system("PAUSE");
}
Any ideas for resolving the ambiguity error in code snippet B?
First, that given 'Derived derived', the compiler is free to choose T =
'Derived' or 'T = Derived const'. Even if the latter would yield a
compilation error (as long as that error isn't covered by SFINAE rules).
And I think this is what's giving you an ambiguity problem.
So you'd want to enforce the same const'ness for types U and T, e.g.,
instead of specifying the argument type as T, specifying it like
'typename ConstVersion<T, IsConst<U>::yes>::Type&'.
Here's an example of detecting constness, not tested:
template< class T >
struct IsConst
{
static T& aT();
static SizeNFalse isConstArg( T& );
static SizeNTrue isConstArg( T const& );
enum{ yes = sizeof( isConstArg( aT() ) ) == sizeof( SizeNTrue ) };
};
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?