Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #7687

Re: Templated Casting operators

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++

Show all headers | View raw


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


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