templates and inheritance

E

er

i have

class Impl; //abstract
class Impl_A:public Impl{...};//abstract
class Impl_B:public Impl{...};//abstract
class Impl_A_0: public Impl_A{/* implements */};

class S{ public: S(Impl*,...); ...};
class S_A: public S{ public: S_A(Impl_A* impl,...):S(impl){};
class S_B: public S{ public: S_B(Impl_B* impl,...):S(impl){};
//hierarchy ends here

template<typename T,typename U>
std::vector<U> mult(T* pimpl){
//calls U(pimpl,...);
};

a) std::vector<S_A> vec(mult<Impl_A0*,S_A>(Impl_A0*)); //ok
b) std::vector<S_A> vec(mult(Impl_A0*)); //compiler error: no
matching function

i would have thought that T and U are implicitly specified by the
input and return type, respectively, so that b) would work?

Overloading like this does not work because i loose information about
the leaf class (Impl_A0* in example):
std::vector<S_A> mult_A(Impl_A* pimpl){return mult(pimpl);}
std::vector<S_B> mult_A(Impl_B* pimpl){return mult(pimpl);}

any suggestion?
 
V

Victor Bazarov

er said:
i have

class Impl; //abstract
class Impl_A:public Impl{...};//abstract
class Impl_B:public Impl{...};//abstract
class Impl_A_0: public Impl_A{/* implements */};

class S{ public: S(Impl*,...); ...};
class S_A: public S{ public: S_A(Impl_A* impl,...):S(impl){};
class S_B: public S{ public: S_B(Impl_B* impl,...):S(impl){};
//hierarchy ends here

template<typename T,typename U>
std::vector<U> mult(T* pimpl){
//calls U(pimpl,...);
};

a) std::vector<S_A> vec(mult<Impl_A0*,S_A>(Impl_A0*)); //ok

OK -- what? 'vec' is a declaration of a function here, methinks.
b) std::vector<S_A> vec(mult(Impl_A0*)); //compiler error: no
matching function

i would have thought that T and U are implicitly specified by the
input and return type, respectively, so that b) would work?

'vec' has overloaded constructors. How should the compiler know
that you intend to use the copy constructor? Yes, if it knew that
the intended specialisation of 'mult' returns a 'vec<S_A>', then
it might figure out that the copy c-tor is needed. But to know
what 'mult' to specialise (and how), it needs to know what your
'vec' constructor accepts as the argument. The classic catch-22.
Overloading like this does not work because i loose information about
the leaf class (Impl_A0* in example):
std::vector<S_A> mult_A(Impl_A* pimpl){return mult(pimpl);}
std::vector<S_B> mult_A(Impl_B* pimpl){return mult(pimpl);}

any suggestion?

What exactly are you trying to accomplish?

V
 
E

er

OK -- what? 'vec' is a declaration of a function here, methinks.



'vec' has overloaded constructors. How should the compiler know
that you intend to use the copy constructor? Yes, if it knew that
the intended specialisation of 'mult' returns a 'vec<S_A>', then
it might figure out that the copy c-tor is needed. But to know
what 'mult' to specialise (and how), it needs to know what your
'vec' constructor accepts as the argument. The classic catch-22.



What exactly are you trying to accomplish?

V

perhaps i should clarify that vec is the name i give to my vector that
i initialize with the output from mult.
 
V

Victor Bazarov

er said:
perhaps i should clarify that vec is the name i give to my vector that
i initialize with the output from mult.

The statement

vector<int> vec(mult(char*));

is not a declaration of a vector. And if 'mult' is a function, it is
a syntax error because a type is passed to the function instead of
a value.

Please follow the recommendations of FAQ 5.8.

V
 
E

er

The statement

vector<int> vec(mult(char*));

is not a declaration of a vector. And if 'mult' is a function, it is
a syntax error because a type is passed to the function instead of
a value.

Please follow the recommendations of FAQ 5.8.

V

ok, i see what you mean. please consider:

ImplA0* pimpl=new Impl_A0;
a) std::vector<S_A> vec=mult<Impl_A0,S_A>(pimpl); //ok
b) std::vector<S_A> vec=mult(pimpl); //compiler error
 
V

Victor Bazarov

er said:
er said:
On Sep 18, 6:39 pm, "Victor Bazarov" <[email protected]>
wrote:
er wrote:
i have
class Impl; //abstract
class Impl_A:public Impl{...};//abstract
class Impl_B:public Impl{...};//abstract
class Impl_A_0: public Impl_A{/* implements */};
class S{ public: S(Impl*,...); ...};
class S_A: public S{ public: S_A(Impl_A* impl,...):S(impl){};
class S_B: public S{ public: S_B(Impl_B* impl,...):S(impl){};
//hierarchy ends here
template<typename T,typename U>
std::vector<U> mult(T* pimpl){
//calls U(pimpl,...);
};
[..]

ok, i see what you mean. please consider:

ImplA0* pimpl=new Impl_A0;
a) std::vector<S_A> vec=mult<Impl_A0,S_A>(pimpl); //ok
b) std::vector<S_A> vec=mult(pimpl); //compiler error

Change your 'mult' definition to

template<class U, class T>
std::vector<U> mult(T* pimpl) { ...

Then you could do

std::vector<S_A> vec = mult<S_A>(pimpl);

The reason it won't work without <S_A> after 'mult' is that
you cannot expect the compiler to deduce the 'U' type without
the argument and unclear return value type (see my mention
of 'catch-22' earlier). The deduction of the template return
value type can only successfully happen if a function pointer
is initialised from a template:

vector<int> (*pf)(char*) = mult;

(should deduce 'U' as 'int' and 'T' as 'char').

V
 

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,744
Messages
2,569,484
Members
44,906
Latest member
SkinfixSkintag

Latest Threads

Top