explicit calling of member template constructor...

W

werasm

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
 
M

Michael Doubez

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.

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 = 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 = ForceType<T>() )
{
F* pf = p;//...
}

};

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

werasm

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
 
S

SG

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

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

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
 
R

red floyd

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!!!!
Shouldn't this line be X<Base> x(&d) ???
 
R

red floyd

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!!!!
Shouldn't this line be X<Base> x(&d) ???
 
M

Michael Doubez

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.
§14.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

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

   X 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.
 
W

werasm

On 24 Mrz., 10:54, Michael Doubez wrote:
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.
§14.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
   struct X
   {
     template <class T>
     X(T*);
   };
   X 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.

Because boost::any when casting back (see its implementation) requires
the exact type, not the polymorphic type....
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top