template class instantiate without template parameter, automatic type deduction

Discussion in 'C++' started by Fei Liu, Oct 25, 2007.

  1. Fei Liu

    Fei Liu Guest

    Hello,
    We all know that a template function can automatically deduce its
    parameter type and instantiate, e.g.

    template <tpyename T>
    void func(T a);

    func(0.f);

    This will cause func<float> to be instantiated. The user does not have
    to explicitly call func<float>(0.f);

    However this line of thinking is broken when it comes to a template
    class constructor function, e.g.

    class A{
    int x;
    };

    template <typename T>
    class C{
    C(const T & t) : t(t) {}
    T t;
    };

    template <>
    class C<A> {
    C(const A & t) : t(t) {}
    A t;
    };


    int main(){

    A a;
    C c(a);
    }

    The above code can't be successfully compiled. One has to name the
    type returned from the constructor call to pick up the object. But
    what really distinguishes from normal function call is that even C(a)
    fails, compiler comlains missing template argument. The problem is
    sometimes you want automatic (auto) type deduction that a compiler can
    provide but you can't get it for constructor call.

    What's the current best practice to approach such kind of problem,
    i.e. automatic type deduction?

    Fei
     
    Fei Liu, Oct 25, 2007
    #1
    1. Advertising

  2. Fei Liu

    Fei Liu Guest

    Re: template class instantiate without template parameter, automatictype deduction

    Fei Liu wrote:
    > Hello,
    > We all know that a template function can automatically deduce its
    > parameter type and instantiate, e.g.


    I apologize for the double posting...Wierd seamonkey email/newsreader
    client issue.
     
    Fei Liu, Oct 25, 2007
    #2
    1. Advertising

  3. Fei Liu wrote:
    > Hello,
    > We all know that a template function can automatically deduce its
    > parameter type and instantiate, e.g.
    >
    > template <tpyename T>
    > void func(T a);
    >
    > func(0.f);
    >
    > This will cause func<float> to be instantiated. The user does not have
    > to explicitly call func<float>(0.f);
    >
    > However this line of thinking is broken when it comes to a template
    > class constructor function, e.g.
    >
    > class A{
    > int x;
    > };
    >
    > template <typename T>
    > class C{
    > C(const T & t) : t(t) {}
    > T t;
    > };
    >
    > template <>
    > class C<A> {
    > C(const A & t) : t(t) {}
    > A t;
    > };
    >
    >
    > int main(){
    >
    > A a;
    > C c(a);
    > }
    >
    > The above code can't be successfully compiled. One has to name the
    > type returned from the constructor call to pick up the object. But
    > what really distinguishes from normal function call is that even C(a)
    > fails, compiler comlains missing template argument.


    Correct. The syntax involves the _type_ name, not a function name.

    > The problem is
    > sometimes you want automatic (auto) type deduction that a compiler can
    > provide but you can't get it for constructor call.


    That's not true at all. In your example it's not the constructor that
    is a template for which the argument needs to be deduced, it's the type
    template that needs to be instantiated. When constructors are concerned,
    this is the correct (and working) example:

    struct C {
    template<class T> C(const T& t) {}
    };

    struct A {};

    int main() {
    A a;
    C c(a); // compiles just fine
    }

    > What's the current best practice to approach such kind of problem,
    > i.e. automatic type deduction?


    Wrap it in a function template.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Oct 25, 2007
    #3
  4. Fei Liu

    Fei Liu Guest

    Re: template class instantiate without template parameter, automatictype deduction

    Victor Bazarov wrote:
    > Fei Liu wrote:
    >> Hello,
    >> We all know that a template function can automatically deduce its
    >> parameter type and instantiate, e.g.
    >>
    >> template <tpyename T>
    >> void func(T a);
    >>
    >> func(0.f);
    >>
    >> This will cause func<float> to be instantiated. The user does not have
    >> to explicitly call func<float>(0.f);
    >>
    >> However this line of thinking is broken when it comes to a template
    >> class constructor function, e.g.
    >>
    >> class A{
    >> int x;
    >> };
    >>
    >> template <typename T>
    >> class C{
    >> C(const T & t) : t(t) {}
    >> T t;
    >> };
    >>
    >> template <>
    >> class C<A> {
    >> C(const A & t) : t(t) {}
    >> A t;
    >> };
    >>
    >>
    >> int main(){
    >>
    >> A a;
    >> C c(a);
    >> }
    >>
    >> The above code can't be successfully compiled. One has to name the
    >> type returned from the constructor call to pick up the object. But
    >> what really distinguishes from normal function call is that even C(a)
    >> fails, compiler comlains missing template argument.

    >
    > Correct. The syntax involves the _type_ name, not a function name.
    >
    >> The problem is
    >> sometimes you want automatic (auto) type deduction that a compiler can
    >> provide but you can't get it for constructor call.

    >
    > That's not true at all. In your example it's not the constructor that
    > is a template for which the argument needs to be deduced, it's the type
    > template that needs to be instantiated. When constructors are concerned,
    > this is the correct (and working) example:
    >
    > struct C {
    > template<class T> C(const T& t) {}
    > };


    Well you see this is not the complete code I presented intially. You
    threw away class member t with your convenient modification. If it needs
    to be:
    template <typenaem U>
    struct C{
    template<class T> C(const T& t) : t(t) {}
    U t;
    };
    We are back to step 1, once you have a class member whose type depends
    on class template parameter.
    >
    > struct A {};
    >
    > int main() {
    > A a;
    > C c(a); // compiles just fine
    > }
    >
    >> What's the current best practice to approach such kind of problem,
    >> i.e. automatic type deduction?

    >
    > Wrap it in a function template.

    Indeed I played with it for a bit, but it does not seem to be that
    great, for example I could conjure a function like following to simulate
    a constructor:
    template <typename T, template <typename > class RT>
    RT<T> create(const T& t){
    return RT<T>(t);
    }

    It quickly becomes obvious that RT<T> needs to be given to instantiate
    it and one does not gain anything.

    Care to supply an example to illustrate your point?
    >
    > V
     
    Fei Liu, Oct 26, 2007
    #4
  5. Fei Liu wrote:
    > Victor Bazarov wrote:
    >> Fei Liu wrote:
    >>> Hello,
    >>> We all know that a template function can automatically deduce its
    >>> parameter type and instantiate, e.g.
    >>>
    >>> template <tpyename T>
    >>> void func(T a);
    >>>
    >>> func(0.f);
    >>>
    >>> This will cause func<float> to be instantiated. The user does not
    >>> have to explicitly call func<float>(0.f);
    >>>
    >>> However this line of thinking is broken when it comes to a template
    >>> class constructor function, e.g.
    >>>
    >>> class A{
    >>> int x;
    >>> };
    >>>
    >>> template <typename T>
    >>> class C{
    >>> C(const T & t) : t(t) {}
    >>> T t;
    >>> };
    >>>
    >>> template <>
    >>> class C<A> {
    >>> C(const A & t) : t(t) {}
    >>> A t;
    >>> };
    >>>
    >>>
    >>> int main(){
    >>>
    >>> A a;
    >>> C c(a);
    >>> }
    >>>
    >>> The above code can't be successfully compiled. One has to name the
    >>> type returned from the constructor call to pick up the object. But
    >>> what really distinguishes from normal function call is that even
    >>> C(a) fails, compiler comlains missing template argument.

    >>
    >> Correct. The syntax involves the _type_ name, not a function name.
    >>
    >>> The problem is
    >>> sometimes you want automatic (auto) type deduction that a compiler
    >>> can provide but you can't get it for constructor call.

    >>
    >> That's not true at all. In your example it's not the constructor
    >> that is a template for which the argument needs to be deduced, it's
    >> the type template that needs to be instantiated. When constructors
    >> are concerned, this is the correct (and working) example:
    >>
    >> struct C {
    >> template<class T> C(const T& t) {}
    >> };

    >
    > Well you see this is not the complete code I presented intially. You
    > threw away class member t with your convenient modification.


    It's not "my convenient modification". It's essential to prove the
    point. A class template argument _cannot_ be deduced from anything
    when trying to define an object of the class instantiated from the
    class template. If it were possible, it would be catch-22. Imagine
    you have

    template<class T> struct C;
    template<> struct C<int> {
    C(char);
    C(double);
    };

    template<> struct C<char> {
    C(bool);
    };

    Now, how the hell should the compiler decide what 'T' should be when
    you declare an object like so

    C a(0);

    ?

    > If it
    > needs to be:
    > template <typenaem U>
    > struct C{
    > template<class T> C(const T& t) : t(t) {}
    > U t;
    > };
    > We are back to step 1, once you have a class member whose type depends
    > on class template parameter.


    No, we're not back to step 1. You're confusing two concepts: defining
    a type with which to declare an object and deduction of the function
    template argument type from the argument the function is called with.

    In this particular case you have two template arguments which are NOT
    related at all. Making your compiler deduce the 'T' (the template
    argument for the constructor) has NO EFFECT on the need to provide
    the template argument for 'C' class template when declaring an object
    with it -- you need a _type_, not a template, to declare an object.

    >>
    >> struct A {};
    >>
    >> int main() {
    >> A a;
    >> C c(a); // compiles just fine
    >> }
    >>
    >>> What's the current best practice to approach such kind of problem,
    >>> i.e. automatic type deduction?

    >>
    >> Wrap it in a function template.

    > Indeed I played with it for a bit, but it does not seem to be that
    > great, for example I could conjure a function like following to
    > simulate a constructor:
    > template <typename T, template <typename > class RT>
    > RT<T> create(const T& t){
    > return RT<T>(t);
    > }
    >
    > It quickly becomes obvious that RT<T> needs to be given to instantiate
    > it and one does not gain anything.
    >
    > Care to supply an example to illustrate your point?


    Well, wrapping the in a function will not really help you declare or
    define a stand-alone object. In order to do that you still need to
    instantiate the template, which requires that you _spell it out_:

    C<blah> ...

    You can, however, use the function wrapper to provide the mechanism
    for instantiating a _temporary_ of your type when using it as part of
    an expression. Given

    template<class T> class C {
    T t;
    public:
    C(T const& t) : t(t) {}
    };

    template<class T> C<T> makeC(T const& t) {
    return C<T>(t);
    }

    you *cannot* write

    ... C(42) ...

    and expect C<int> to be instantiated. You still would have to write

    ... C<int>(42) ...

    However, you *can* write

    ... makeC(42) ...

    in which case a temporary of type C<int> _will_ be created (after
    C<int> is instantiated). That's what I meant.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Oct 26, 2007
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Neelesh

    Template parameter Deduction

    Neelesh, Nov 10, 2005, in forum: C++
    Replies:
    4
    Views:
    445
    John Carson
    Nov 10, 2005
  2. Fei Liu
    Replies:
    0
    Views:
    432
    Fei Liu
    Oct 25, 2007
  3. KD
    Replies:
    4
    Views:
    338
    Road.Tang
    Jun 20, 2008
  4. er
    Replies:
    5
    Views:
    1,350
  5. Replies:
    2
    Views:
    344
Loading...

Share This Page