开发者

Doubt with the template instantiation problem in the below snippet of a user defined class [duplicate]

This question already has answers here: 开发者_如何学Python "template polymorphism" when calling function for templated parameter of base type, with derived type? (2 answers) Closed 8 years ago.

Couldn't find anything relevant in forums So ,Please help me with this code .I'm brushing up my c++ concepts and met with a strange error

#include<iostream>
using namespace std ;
class base
{
    int i ;
public:
    virtual void f(){cout<<"base" ; return ;};
};
class derived: public base
{
int j ;
public:
    void f() {cout<<"derived" ; return ;}
};
template<class T>
class test
{
public:
    test(T b) 
    {
        b.f(); cout<<endl<<" "<<sizeof(b)<<endl;
    }
};
int main()
{
base b ;
derived d;
test<derived> t(b); // cannot instantiate user defined type without typename
}

The following code fails to compile with the following error :

test.cpp: In function ‘int main()’:
test.cpp:28: error: no matching function for call to ‘test<derived>::test(base&)’
test.cpp:19: note: candidates are: test<T>::test(T) [with T = derived]
test.cpp:17: note:  test<derived>::test(const test<derived>&)

I can make wild guess and arrive at an answer at to why did this happen .If i instantiate a new base class from the template , everything works just fine , but not this one . Can somebody tell me a good source for template instantiations and what are the rules/semantics , what is happening behind the curtain ? thanks


Your test snippet effectively defines this:

test::test(derived&)

As the error says, you're trying to invoke this instead:

test::test(base&)

If i instantiate a new base class from the template , everything works just fine.

Similarly, I'm sure, if you passed "d" instead of "b", everything would also work fine.

You should be able to reproduce the same scenario without templates: just defined a member function that takes "derived" as an argument, and see what happens :)


base is not a complete derived type, so you'll have to provide a constructor inside your template that fills in the missing details.

template<class T> //original template
class test
{
  public:
    test(T b)
    {
      b.f();
      cout<<endl<<" "<<sizeof(b)<<endl;
    }
};

When you create an instance of this template based on derived, the compiler translates it to a class, which essentially boils down to this

class derivedtest
{
  public:
    derivedtest(derived b)
    {
      b.f();
      cout<<endl<<" "<<sizeof(b)<<endl;
    }
};

The default constructor is not generated any more. However, a default copy constructor is still created.

derivedtest::derivedtest(derived const&);

As you can see, there is no way to pass base (by reference or copy) into the class.

The solution is to provide a constructor inside your template that fills in the missing details:

template<class T>
class test
{
  public:
    test(base const& item)
     : base(item)
    {
    }


    test(T b)
    {
      b.f();
      cout<<endl<<" "<<sizeof(b)<<endl;
    }
};

By the way, your base should most likely have a virtual destructor

and test(T b) should be test(T const& b)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜