模板<class t =“”>错误</class>

时间:2011-05-23 09:25:15

标签: c++

我有一个:header.cpp,header.hpp和一个test_header.cpp。

在header.hpp中,我有:

class MyClass
  {
    public;
    MyClass();
    std::string name;
    //...code with other variables,methods;

 class MySecondClass
  {

    public:
    MySecondClass();

    std::string surname;
    //..code with other variables,methods

  }*MySC;

   public:
   template<class T>
   bool method(T& obj);

    {



    if (typeid(MyClass)=typeid(obj))
     {
       MyClass *s= new MyClass();
        *s=obj //i want to save everything that i have in obj into s;
        //call  method "MyMethod" and work with s

    }
     else if (typeid(MyClass::MySecondClass)=typeid(obj))
      {
        MyClass::MySecondClass *s1= new MyClass::MySecondClass();
        *s1 = obj;
        //call "MyMethod" and work with s1;
      }
     return true;
  }

}*mycls;

在test_header.cpp中我有

{
  MyClass *mycls = new MyClass();
  MyClass::MySecondClass *mysec_cls= new MyClass::MySecondClass();

   if (mycls->method<MyClass>(*mycls) 
              {//code
               }
   if (mycls->method<MyClass::MySecondClass>(*mysec_cls)
           {//code
           }
}

我有一个错误,说mysec_cls不是MyClass类型。因为我已经意识到指针转到第一个if而且从不在其他地方。

.h error: no match for operator= in *s1 = obj. 
note: candidates are: MyClass& MyClass::operator=(const MyClass&)

我没有这个错误,如果在test_header.cpp我只有一个if和if在模板中我只有if in test_header中的引用,但是如果我对T&amp; obj我有我提到的错误。

为什么呢?怎么改变这个?我正在使用g ++进行编译。

2 个答案:

答案 0 :(得分:4)

当你实例化一个模板时,它会被完全编译,而不管代码的哪些分支最终会被执行。在您的特定代码中,即使if语句将确保仅执行具有有效赋值的分支,也必须编译这两个分支,并且其中一个分支不正确。

考虑简单的非模板化示例:

void foo( int x ) {
   if ( true ) {
      int y = x;
   } else {
      std::string s = x;
   }
}

虽然永远不会执行第二个分支,但编译器必须确保代码正确(即使它可以优化它),并且它将失败,因为您无法从整数初始化字符串。您的代码中存在同样的问题。

至于如何解决它,最简单的方法是,不使用函数重载解析来代替编写分支,而是将调度解析为适当的代码段。这样你可以有两个不同的函数(或者如果你想要的话可​​以使用特殊化,但我建议使用不同的重载),每个函数只能使用其中一种类型,这样分配才有效。

答案 1 :(得分:1)

我的水晶球告诉我你以某种方式使你从type_info中检索的类名变形,因为这个名字不是直接的类名,而是一个实现定义的字符串,它充分地从类名派生,以允许相等比较,并且在那个过程中,两个名称都被映射到“MyClass”(即你正在切断内部类的名称),因此它们最终都在同一个处理程序中。

如果要在运行时比较类型,请直接比较type_info节点:

if(typeid(obj) == typeid(MyClass)) ...

如果你在method中有一个关闭的类型列表(在你的实现中,因为你不能将更多的案例添加到链式if语句列表中),那么就没有了使用模板的真正原因;定期超载就足够了:

class MyClass
{
    std::string name;
    // ...
    class MySecondClass
    {
        std::string surname;
        // ...
    } *mysc;

    bool method(MyClass const &obj)
    {
        MyClass *copy = new MyClass;
        *copy = obj;
        // ...
    }
    bool method(MySecondClass const &obj)
    {
        MySecondClass *copy = new MySecondClass;
        *copy = obj;
        // ...
    }
    // ...
};