Re: Templated Casting operators
On Jul 8, 9:37 am, Narinder <narinder.cla...@gmail.com> wrote:
On Jul 8, 8:42 am, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
Narinder wrote:
[...]
Consider the following code:
-------------------------------------------------------------
#include<iostream>
using namespace std;
double pi =3.142;
struct klass
{
template<class T>
operator T&()
{
cout << "I am NON-const version\n";
return pi;
}
template<class T>
operator const T&()const
{
cout << "I am CONST version\n";
return pi;
}
};
template<class T>
T& show(T &t)
{
cout << "NON-CONST show\n";
return t;
}
template<class T>
const T& show(const T &t)
{
cout << "CONST show\n";
return t;
}
int main()
{
klass k;
show(k);
show(klass());
double x1 = k;
double x2 = klass();
}
-----------------------------------------------------
Output from msvc :
NON-CONST show
CONST show
I am CONST version
I am CONST version
Output from gcc
NON-CONST show
CONST show
I am NON-CONST version
I am NON-CONST version
To me the msvc appears 'correct' or at least self-consistent. Or
perhaps I am missing something.
Any thoughts ?
I think, gcc gets it right and lets you observe a language quirk: In th=
is
version, the two conversion operators differ by constness. Thus, overlo=
ad
resolution should be based on constness of the klass object being conve=
rted:
klass k; // declares a non-const klass object k
show(k); // should choose the T& version
show( klass() ); // should choose the T const & version because of =
8.5.3/5
double x1 = k; // should choose the non-const member as k is non-=
const
double x2 = klass(); // should choose the non-const member as the
// temporary klass() is =
non-const
The last issue is an inconsistency in the language: though klass() is n=
on-
const, the temporary cannot be used to initialize a non-const reference=
..
Best,
Kai-Uwe Bux
Hi,
Thanks for the reply,
For the following code:
---------------------------------
#include<iostream>
using namespace std;
double pi = 3.142;
struct klass
{
template<class T>
operator T&()
{
cout << "I am NON-const vers=
ion\n";
return pi;
}
template<class T>
operator const T&()
{
cout << "I am CONST version\=
n";
return pi;
}
};
int main()
{
klass k;
double x = k;
double x2 = klass();
}
---------------------------------
msvc =>
I am CONST version
I am CONST version
and gcc =>
I am NON-const version
I am NON-const version
Which one would you say adhere's to language correctness and which one
is
desired ?
N
Hello,
To elaborate on this a little more, I'll put the issue that I have in
a
context more closer to my actual scenario.
The following code compiles and executes fine under msvc but throws
under
gcc. I think the behaviour under gcc is much less desirable. I am
curious
about the language's rationale behind this:
---------------------------------------------------
#include<iostream>
#include<boost/ref.hpp>
#include<boost/variant.hpp>
using namespace std;
double pi = 3.142;
typedef boost::reference_wrapper<double> ref;
typedef boost::reference_wrapper<const double> const_ref;
struct klass
{
klass(double & x):innerVariant(boost::ref(x)){}
klass(const double & x):innerVariant(boost::cref(x)){}
template<class T>
operator T&()
{
cout << "Attempting non-con=
st cast .... ";
return boost::get<ref >(innerV=
ariant);
}
template<class T>
operator const T&()
{
cout << "Attempting const c=
ast .... ";
if(boost::get<ref >(&innerVari=
ant))
{
return=
boost::get<ref >(innerVariant);
}
return boost::get<const_ref >(=
innerVariant);
}
private:
boost::variant<ref,const_ref > innerVariant;
};
void f(double &x)
{
cout << "double &x\n";
}
void fc(const double &x)
{
cout << "const double &x\n";
}
void ft(double x)
{
cout << "double\n";
}
int main()
{
try
{
double x(3.142);
klass k_non_const(x);
klass k_const(3.142);
f(k_non_const);
fc(k_non_const);
ft(k_non_const);
fc(k_const);
ft(k_const); // this one throws with gcc
}
catch(const std::exception &err)
{
cout << err.what() << "\n";
}
}
-----------------------------------------------
N