explicit calling of member template constructor...

  • Follow


Hi All,

I have this example that attempts to call a member template
constructor
whilst explicitly specifying the template parameters. I realize that
by using
static_cast one can force the parameters to the right type (via
argument
deduction), but for normal member templates one [can] explicitly
specify
the template parameters. I would think there would be consistency
here.

Example:

struct X
{
  template <class T>
  X( T* p );
  template <class T>
  X foo( T* p );
};

struct Base{};
struct Derived : Base{};


void foo( const X& );

int main()
{
  Derived d;
  //X x<Base>( &d ); //Does not compile!!!!
  X x( static_cast<Base*>(&d) );

  foo( x.foo( &d ) );
  foo( x.foo<Base>( &d ) ); //Does compile!!!
}

Any comments as to why this is so appreciated, Thanks.

Werner
0
Reply werasm 3/24/2010 9:17:16 AM

On 24 mar, 10:17, werasm <wer...@gmail.com> wrote:
> Hi All,
>
> I have this example that attempts to call a member template
> constructor
> whilst explicitly specifying the template parameters. I realize that
> by using
> static_cast one can force the parameters to the right type (via
> argument
> deduction), but for normal member templates one [can] explicitly
> specify
> the template parameters. I would think there would be consistency
> here.
>
> Example:
>
> struct X
> {
> =A0 template <class T>
> =A0 X( T* p );
> =A0 template <class T>
> =A0 X foo( T* p );
>
> };
>
> struct Base{};
> struct Derived : Base{};
>
> void foo( const X& );
>
> int main()
> {
> =A0 Derived d;
> =A0 //X x<Base>( &d ); //Does not compile!!!!
> =A0 X x( static_cast<Base*>(&d) );
>
> =A0 foo( x.foo( &d ) );
> =A0 foo( x.foo<Base>( &d ) ); //Does compile!!!
>
> }
>
> Any comments as to why this is so appreciated, Thanks.

Because constructors do not have names.

As for your problem, it is easily solved by using a (1) construction
function or (2) passing an additional parameter.

(1)
struct X
{
  template <class T>
  static X make( T* p );

  template <class T>
  X foo( T* p );
};

X x =3D X::make<Base>(&d);

(2)
template<class T>
struct ForceType { };

struct X
{
  template <class T, class F >
  X( T* p , const ForceType<F>& force_type =3D ForceType<T>() )
  {
    F* pf =3D p;//...
  }

};

X x(&d,ForceType<Base>());

--
Michael
0
Reply Michael 3/24/2010 9:54:40 AM


On Mar 24, 11:54=A0am, Michael Doubez <michael.dou...@free.fr> wrote:

> Because constructors do not have names.

Yes, I realize that there must be a way to discern between member
templates and the class template (the name used for the class
template). I was wondering if there is
perhaps a way

e.g: X.template x<Base>( &d );
// Calls member template constructor, instantiating
// x of type X...

I can accept that the use for something to this effect will be rare.
I've
decided on simply using static cast:

X x( static_cast<Base>( Derived*(0) );

Kind regards,

Werner
0
Reply werasm 3/24/2010 10:26:21 AM

On 24 Mrz., 10:54, Michael Doubez wrote:
> (2)
>   template<class T>
>   struct ForceType { };
>
>   struct X
>   {
> =A0   template <class T, class F >
> =A0   X( T* p , const ForceType<F>& force_type =3D ForceType<T>() )
> =A0   {
> =A0   =A0 F* pf =3D p;//...
> =A0   }
>   };
>
>   X x(&d,ForceType<Base>());

The default parameter doesn't work here. At least G++ is rejecting it
and I think this is because F cannot be deduced by the default
parameter. Since you need to supply some dummy ForceType<>-Object so
that F can be deduced you could reduce the number of template
parameters and instantiations via

   template<class T>struct identity{typedef T type;};

   struct X
   {
     template <class T>
     X(identity<T>, typename identity<T>::type* p);
     // ^^^^^^^^^^  ^^^^^^^^^^^^^^^^^^^^^^^^^^
     //     (1)                 (2)
     //
     // 1: type tag, used for template argument deduction
     // 2: prevents template argument deduction for the
     //    second parameter
   };

   :

   derived d;
   X x(identity<base>(),&d);  // 3

This has also the benefit of the implicit pointer conversion being
outside of the constructor. In case this conversion is ill-formed the
compiler will point you to the offending line (3) instead of pointing
you to the constructor of X.

But I honestly see no advantage over

   struct X
   {
     template <class T>
     X(T*);
   };

   X x(static_cast<base*>(&d));

Cheers,
SG
0
Reply SG 3/24/2010 10:48:08 AM

On Mar 24, 2:17=A0am, werasm <wer...@gmail.com> wrote:
> Hi All,
>
> I have this example that attempts to call a member template
> constructor
> whilst explicitly specifying the template parameters. I realize that
> by using
> static_cast one can force the parameters to the right type (via
> argument
> deduction), but for normal member templates one [can] explicitly
> specify
> the template parameters. I would think there would be consistency
> here.
>
> Example:
>
> struct X
> {
> =A0 template <class T>
> =A0 X( T* p );
> =A0 template <class T>
> =A0 X foo( T* p );
>
> };
>
> struct Base{};
> struct Derived : Base{};
>
> void foo( const X& );
>
> int main()
> {
> =A0 Derived d;
> =A0 //X x<Base>( &d ); //Does not compile!!!!
Shouldn't this line be X<Base> x(&d) ???
0
Reply red 3/24/2010 5:02:55 PM

On Mar 24, 2:17=A0am, werasm <wer...@gmail.com> wrote:
> Hi All,
>
> I have this example that attempts to call a member template
> constructor
> whilst explicitly specifying the template parameters. I realize that
> by using
> static_cast one can force the parameters to the right type (via
> argument
> deduction), but for normal member templates one [can] explicitly
> specify
> the template parameters. I would think there would be consistency
> here.
>
> Example:
>
> struct X
> {
> =A0 template <class T>
> =A0 X( T* p );
> =A0 template <class T>
> =A0 X foo( T* p );
>
> };
>
> struct Base{};
> struct Derived : Base{};
>
> void foo( const X& );
>
> int main()
> {
> =A0 Derived d;
> =A0 //X x<Base>( &d ); //Does not compile!!!!
Shouldn't this line be X<Base> x(&d) ???
0
Reply red 3/24/2010 5:03:06 PM

On 24 mar, 11:48, SG <s.gesem...@gmail.com> wrote:
> On 24 Mrz., 10:54, Michael Doubez wrote:
>
> > (2)
> > =A0 template<class T>
> > =A0 struct ForceType { };
>
> > =A0 struct X
> > =A0 {
> > =A0 =A0 template <class T, class F >
> > =A0 =A0 X( T* p , const ForceType<F>& force_type =3D ForceType<T>() )
> > =A0 =A0 {
> > =A0 =A0 =A0 F* pf =3D p;//...
> > =A0 =A0 }
> > =A0 };
>
> > =A0 X x(&d,ForceType<Base>());
>
> The default parameter doesn't work here. At least G++ is rejecting it
> and I think this is because F cannot be deduced by the default
> parameter.

Yes.
=A714.8.2/17: a template type-parameter cannot be deduced from the type
of a function default argument.

[snip]
> But I honestly see no advantage over
>
> =A0 =A0struct X
> =A0 =A0{
> =A0 =A0 =A0template <class T>
> =A0 =A0 =A0X(T*);
> =A0 =A0};
>
> =A0 =A0X x(static_cast<base*>(&d));

From the very beginning the question is biased: if you have a template
argument, I don't the reason why you would want to instantiate it with
a base class.
Unless the member function became protected in the derived but then
the cast should obviously be explicit.

--
Michael
0
Reply Michael 3/25/2010 8:47:45 AM

On Mar 25, 10:47=A0am, Michael Doubez <michael.dou...@free.fr> wrote:
> On 24 mar, 11:48, SG <s.gesem...@gmail.com> wrote:
>
>
>
> > On 24 Mrz., 10:54, Michael Doubez wrote:
>
> > > (2)
> > > =A0 template<class T>
> > > =A0 struct ForceType { };
>
> > > =A0 struct X
> > > =A0 {
> > > =A0 =A0 template <class T, class F >
> > > =A0 =A0 X( T* p , const ForceType<F>& force_type =3D ForceType<T>() )
> > > =A0 =A0 {
> > > =A0 =A0 =A0 F* pf =3D p;//...
> > > =A0 =A0 }
> > > =A0 };
>
> > > =A0 X x(&d,ForceType<Base>());
>
> > The default parameter doesn't work here. At least G++ is rejecting it
> > and I think this is because F cannot be deduced by the default
> > parameter.
>
> Yes.
> =A714.8.2/17: a template type-parameter cannot be deduced from the type
> of a function default argument.
>
> [snip]
>
> > But I honestly see no advantage over
>
> > =A0 =A0struct X
> > =A0 =A0{
> > =A0 =A0 =A0template <class T>
> > =A0 =A0 =A0X(T*);
> > =A0 =A0};
>
> > =A0 =A0X x(static_cast<base*>(&d));
>
> From the very beginning the question is biased: if you have a template
> argument, I don't the reason why you would want to instantiate it with
> a base class.
> Unless the member function became protected in the derived but then
> the cast should obviously be explicit.
>
> --
> Michael

Because boost::any when casting back (see its implementation) requires
the exact type, not the polymorphic type....
0
Reply werasm 3/25/2010 10:35:46 AM

7 Replies
325 Views

(page loaded in 0.056 seconds)

Similiar Articles:













7/26/2012 9:16:30 PM


Reply: