Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #7687
| From | Kai-Uwe Bux <jkherciueh@gmx.net> |
|---|---|
| Newsgroups | comp.lang.c++ |
| Subject | Re: Templated Casting operators |
| Followup-To | comp.lang.c++ |
| Date | 2011-07-10 01:15 +0200 |
| Organization | University of Bielefeld |
| Message-ID | <ivanek$g9k$1@hoshi.visyn.net> (permalink) |
| References | (4 earlier) <8aed9603-26d2-41fb-b197-213bdf90ff99@34g2000yqr.googlegroups.com> <iv7v24$oo9$1@hoshi.visyn.net> <f966f5b5-a173-45f5-b1ea-035ca5977502@n5g2000yqh.googlegroups.com> <iv9ed1$67q$1@hoshi.visyn.net> <b781d567-f97a-4951-b3fb-b6702884a8d8@h12g2000vbx.googlegroups.com> |
Followups directed to: comp.lang.c++
Narinder wrote:
> On Jul 9, 12:34 pm, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
>> Narinder wrote:
>> >>On Jul 8, 11:06 pm, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
>> >>At the moment, I don't see why.
>>
>> > That is indeed curious.
>> > However on my issue, I think I am expecting something from C++ .. when
>> > I obviously should know better, "C++ (101): C++ doesn't dispatch on
>> > the return type".
>>
>> That, I think, is not the entire picture. There is clause [14.8.2.3] that
>> deals with deducing template arguments for templated conversion
>> operators. Here, the result type desired by the conversion is taken into
>> account. Howerver, reading that clause, I find it hard to tell whether
>> the deduction should fail because of ambiguity, whether the const version
>> should be instantiated, or whether the non-const version should be
>> chosen.
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> > My question stems from wanting to pass parameters to a function via an
>> > intermediary which holds references to the values to be passed. And
>> > this would be done at runtime.
>>
>> > Given :
>>
>> > void f( double x);
>>
>> > I want to be able to do:
>>
>> > const double x=3.142;
>> > intermediary v = x; // so v will hold a
>> > std::tr1::reference_wrapper<const double>
>> > f(v); // I suspect gcc will complain because v is unable
>> > to give up its const ref
>> > // but as we have seen gcc calls operator
>> > double&()
>>
>> Hm, the following compiles:
>>
>> #include <iostream>
>>
>> void foo ( double arg ) {
>> std::cout << arg << "\n";
>>
>> }
>>
>> template < typename T >
>> class reference_wrapper {
>>
>> T* the_ptr;
>>
>> public:
>>
>> typedef T type;
>> typedef T& reference;
>>
>> reference_wrapper ( reference t_ref )
>> : the_ptr ( &t_ref )
>> {}
>>
>> operator reference ( void ) {
>> return ( *the_ptr );
>> }
>>
>> reference get ( void ) {
>> return ( *the_ptr );
>> }
>>
>> };
>>
>> int main ( void ) {
>> double const pi = 3.14159;
>> reference_wrapper< double const > x = pi;
>> foo( x );
>>
>> }
>> > My way around this will be to have the user provide a precise boost
>> > typelist embodying the function signature:
>>
>> > boost::mpl::vector<double>
>>
>> > and use this to dispatch correctly.
>>
>> Huh?
>>
>> Best,
>>
>> Kai-Uwe Bux
>
> Consider the following functions:
>
> f_ref(double&) // may be a member function that keeps the
> rw ref
> f_const_ref(const double&) // maybe a memeber function that keeps the
> ro ref
> f_val(double) // expects the value byval
>
> you have one 'variant'
>
> variant v = 3.142;
>
> double x=3.142;
> variant v2 = x;
>
> const double xx=3.142
> variant v3 = 3.142
>
> I want to deliver (since it doesn't have to be done by casting) v2 to
> f_ref, but not v & v3
> I want to deliver v2 & v3 to f_const_ref but not v
> and i want to be able to deliver all of them to f_val
>
> Moreover my variants will be initialised at runtime.
>
>
> I have sketched (but compiles and executes ) what I think is a
> solution.
> (I have used boost::mpl::vector to be able to generalise to more than
> one parameter)
>
> -------------------------------
> #include<iostream>
> #include<boost/ref.hpp>
> #include<boost/variant.hpp>
> #include<boost/mpl/vector.hpp>
> #include<boost/mpl/at.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 << " ... casting to double& ";
> return boost::get<ref>(innerVariant);
> }
>
> template<class T>
> operator const T&()
> {
> cout << " ... casting to const double& ";
> if(boost::get<ref>(&innerVariant))
> {
> return boost::get<ref>(innerVariant);
> }
> return boost::get<const_ref>(innerVariant);
>
> }
>
>
> const double &get_by_val()
> {
> return (const double&)(*this);
> }
>
>
> private:
> boost::variant<ref,const_ref > innerVariant;
> };
>
> template<class T,class U>
> struct innerCast
> {
> static const T & get(U &k)
> {
> return k.get_by_val();
> }
> };
>
> template<class T,class U>
> struct innerCast<T&,U>
> {
> static T & get(U &k)
> {
> return k;
> }
> };
>
> template<class T,class U>
> struct innerCast<const T&,U>
> {
> static const T & get(U &k)
> {
> return k;
> }
> };
>
>
> template<class T>
> struct cast
> {
> typedef typename boost::mpl::at_c<typename T::param_type,0>::type
> ret_type;
>
> static ret_type get(klass &k)
> {
> return innerCast<ret_type,klass>::get(k);
> }
>
> };
>
>
> /////////////////////////////////////////
> // Below is what would be the user code
> /////////////////////////////////////////
>
> struct f
> {
> typedef boost::mpl::vector<double&>::type param_type;
> static void call(double &x)
> {
> cout << " double &x\n";
> }
> };
>
> struct fc
> {
> typedef boost::mpl::vector<const double&> param_type;
> static void call(const double &x)
> {
> cout << " const double &x\n";
> }
> };
>
> struct ft
> {
> typedef boost::mpl::vector<double> param_type;
> static void call(double x)
> {
> cout << " double\n";
> }
>
> };
>
> int main()
> {
>
> try
> {
>
> double x(3.142);
>
> klass k_non_const(x);
> klass k_const(3.142);
>
> f::call( cast<f>::get(k_non_const) );
> fc::call( cast<fc>::get(k_non_const));
> ft::call( cast<ft>::get(k_non_const));
>
> fc::call( cast<fc>::get(k_const));
> ft::call( cast<ft>::get(k_const)); // this one *NO LONGER*
> throws with gcc
> }
> catch(const std::exception &err)
> {
> cout << err.what() << "\n";
> }
>
> }
>
> ---------------------------------------------
>
> Maybe some of the class names have alot of scope to be more
> meaningful :-)
Here is an alternative idea (hopefully, I understood your aim):
#include <iostream>
struct oops {};
template < typename T >
class const_reference {
T const * ptr;
public:
const_reference ( T const & r )
: ptr ( &r )
{}
T const & get ( void ) {
return ( *ptr );
}
operator T const & ( void ) {
return ( *ptr );
}
};
template < typename T >
class reference {
T * ptr;
public:
reference ( T & r )
: ptr ( &r )
{}
T & get ( void ) {
return ( *ptr );
}
operator T & ( void ) {
return ( *ptr );
}
};
template < typename T >
class wrapper {
private:
T * the_ptr;
T const * the_c_ptr;
public:
wrapper ( T & ref )
: the_ptr ( &ref )
, the_c_ptr ()
{}
wrapper ( T const & cref )
: the_ptr ()
, the_c_ptr ( &cref )
{}
operator reference<T> ( void ) {
std::cout << "non-const\n";
if ( the_ptr ) {
return ( *the_ptr );
}
throw ( oops() );
}
operator const_reference<T> ( void ) {
std::cout << "const\n";
if ( the_ptr ) {
return ( *the_ptr );
}
return ( *the_c_ptr );
}
operator T ( void ) {
if ( the_ptr ) {
return ( *the_ptr );
}
return ( *the_c_ptr );
}
};
double const pi = 3.14159;
double e = 2.71828;
typedef wrapper< double > klass;
void foo_ref ( reference<double> ) {
std::cout << "reference\n";
}
void foo_cref ( const_reference<double> ) {
std::cout << "const reference\n";
}
void foo_val ( double ) {
std::cout << "value\n";
}
int main ( void ) {
klass rw ( e );
klass ro ( pi );
foo_val( rw );
foo_cref( rw );
foo_ref( rw );
foo_val( ro );
foo_cref( ro );
foo_ref( ro );
}
Best,
Kai-Uwe Bux
Back to comp.lang.c++ | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
Templated Casting operators Narinder <narinder.claire@gmail.com> - 2011-07-07 16:34 -0700
Re: Templated Casting operators Alexander Bartolich <alexander.bartolich@gmx.at> - 2011-07-08 00:58 +0000
Re: Templated Casting operators Narinder <narinder.claire@gmail.com> - 2011-07-07 22:36 -0700
Re: Templated Casting operators Kai-Uwe Bux <jkherciueh@gmx.net> - 2011-07-08 09:42 +0200
Re: Templated Casting operators Narinder <narinder.claire@gmail.com> - 2011-07-08 01:16 -0700
Re: Templated Casting operators Ian Collins <ian-news@hotmail.com> - 2011-07-08 20:23 +1200
Re: Templated Casting operators Narinder <narinder.claire@gmail.com> - 2011-07-08 01:37 -0700
Re: Templated Casting operators Narinder <narinder.claire@gmail.com> - 2011-07-08 06:28 -0700
Re: Templated Casting operators Narinder <narinder.claire@gmail.com> - 2011-07-08 01:40 -0700
Re: Templated Casting operators Kai-Uwe Bux <jkherciueh@gmx.net> - 2011-07-09 00:06 +0200
Re: Templated Casting operators Narinder <narinder.claire@gmail.com> - 2011-07-09 03:16 -0700
Re: Templated Casting operators Kai-Uwe Bux <jkherciueh@gmx.net> - 2011-07-09 13:34 +0200
Re: Templated Casting operators Narinder <narinder.claire@gmail.com> - 2011-07-09 07:18 -0700
Re: Templated Casting operators Kai-Uwe Bux <jkherciueh@gmx.net> - 2011-07-10 01:15 +0200
Re: Templated Casting operators Narinder <narinder.claire@gmail.com> - 2011-07-09 21:39 -0700
Re: Templated Casting operators Narinder <narinder.claire@gmail.com> - 2011-07-09 22:01 -0700
Re: Templated Casting operators Kai-Uwe Bux <jkherciueh@gmx.net> - 2011-07-10 13:43 +0200
Re: Templated Casting operators Narinder <narinder.claire@gmail.com> - 2011-07-10 05:55 -0700
Re: Templated Casting operators Narinder <narinder.claire@gmail.com> - 2011-07-10 00:19 -0700
Re: Templated Casting operators Kai-Uwe Bux <jkherciueh@gmx.net> - 2011-07-10 12:03 +0200
csiph-web