1

I have a: header.cpp, header.hpp and a test_header.cpp.

In header.hpp i've i have:

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;

In test_header.cpp I have

{
  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
           }
}

I have an error saying that mysec_cls is not of type MyClass. As i've realised the pointer goes to the first if and never on else.

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

I don't have this error if in test_header.cpp i have just one if and if in template i only have the reference from the if in test_header, but if ihave more than one refference to T& obj i have the error i've mentioned.

Why? how to change this? i am compiling using g++.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
marryy
  • 215
  • 1
  • 6
  • 13
  • 1
    Could you fix the indentation on your code snippet please? – Oliver Charlesworth May 23 '11 at 09:28
  • a clear case where simple overloading will save you a lot of effort.. anyway, you're code is incomprehensible - you need to put together a clearer example, and you are likely to get some answers... – Nim May 23 '11 at 09:32
  • 1
    From your question, it sounds like you've removed the code that's obviously faulty: //using std::type_info& and typeid i obtain the ype of the obj; in the std::string s i retain the name of the obj and after that.. – Tony Delroy May 23 '11 at 09:38
  • What is this strange syntax? `class MyClass {} *mycls;` and `class MySecondClass {} *MySC;`? What do you hope to achieve by this? – Nim May 23 '11 at 09:48
  • @Nim, that syntax is creating the type (`class MyClass {}`) and creating a variable of type *pointer-to-newly-created-type*. Basically equivalent to `class MyClass {}; class MyClass *mycls;` – David Rodríguez - dribeas May 23 '11 at 09:52
  • @David, I understand that ;), I was trying to see if the OP understood this too.... – Nim May 23 '11 at 09:55
  • Sorry, the use of typeid and templates is wrong and totally ridiculous. Templates are for the case where you don't care what the type is (beyond some operations being defined for it), but you have special cases for particular types, so you should be using overloaded functions. And you should use dynamic_cast instead of typeid to check whether object is of particular dynamic type. Both only work and make sense for polymorphic types (with virtual methods and being refered to by base pointer/reference) (not making an answer, because you already have them for both key points). – Jan Hudec May 23 '11 at 09:58
  • can you help me? i don't know how to solve the error. – marryy May 23 '11 at 12:01
  • could u rewrite the code using dynamic cast? – marryy May 23 '11 at 12:15

2 Answers2

4

When you instantiate a template it gets fully compiled, independently of what branches of the code will get eventually executed. In your particular code, even if the if statement will ensure that only the branch that has the valid assignment gets executed, both branches must be compiled, and one of them is not correct.

Consider the simple non templated example:

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

While the second branch will never be executed, the compiler must ensure that the code is correct (even if it can optimize it away), and it will fail as you cannot initialize a string from an integer. The same problem is present in your code.

As to how to solve it, the simplest way would be that instead of writing branches you use function overload resolution to resolve the dispatch to the appropriate piece of code. That way you can have two different functions (or specializations if you want, but I'd recommend different overloads), each of which works only with one of the types, so that the assignment is valid.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • You could have posted this in your old post (after erasing it). – Nawaz May 23 '11 at 09:55
  • 2
    Once I realized the answer was wrong, I deleted it immediately, I did not want anyone to get confused in the mean-time with a wrong answer while I wrote this one. For most people the old answer does not even appear anymore, and for those of us that can see it, it appears at the end of the list. I think we have a different point of view to this respect (from what I have seen in the past), to me this is not a modification to the old answer, but rather a new different one. Modifying the answer (rather than editing for minor mistakes or additional info) only makes things more confusing to others. – David Rodríguez - dribeas May 23 '11 at 10:03
  • @David: No. What I meant was that you could have edited the same post after deleting that, and once you're done with the correct answer, you can *undelete* your post. That way we will not have an extra post which is visible to many of us. Also, your deleted post appears at the top, not at the end (at least to me). – Nawaz May 23 '11 at 10:06
  • @Nawaz: I understand what you mean, but I am not sure that you understand what I mean: This is not a modification of the other answer. The other answer was wrong and deleted. This is a *different* answer that I have written afterwards. That detail is what makes the difference to me: this is not an update of the other answer this is a completely different one. And the side effect of others (high rep users) being able that I misinterpreted the question, well, I don't think that the extra greyed out answer at the end can be considered *disturbing* by any means. The alternative is much worse. – David Rodríguez - dribeas May 23 '11 at 10:28
  • @David: I very well understand that its a different answer; the old one was admittedly incorrect, that is why you wrote this. All I'm saying is that you could have posted this "different" answer in the same post, erasing the old incorrect content. Suppose if few more users follow your pattern of deleting and adding another post, then there will be more than one posts per such user, even when only one of them is correct answer, and others will be unnecessarily visible to many of us. – Nawaz May 23 '11 at 10:42
  • [contd] If you still didn't understand, then ask yourself : what if you realize that you again misunderstood the question, then would you delete this and add a new post again? Or you would erase the content and write the new answer in this post itself? – Nawaz May 23 '11 at 10:45
  • 1
    @Nawaz: This discussion can get as long as we both want, you believe that there should be less posts because you somehow feel that the extra greyed out post at the end is disturbing. I believe that an incorrect answer is to be deleted, even if a correct is to be added, and the premise is that otherwise any extra information attached to the question will be misleading. This is not the particular case today, but you can go back to your answers, and figure out how many of the comments left in your modified answers are unrelated to the final version of your answer. I find that much more disturbing – David Rodríguez - dribeas May 23 '11 at 12:10
  • [cont'd] and not only for the high reputed users at the end of the page, but for all users visible *together* with the answer. I already told you that I understand what you mean, but I do not share your point of view. You aim to reduce the number of answers that high rep users can see --even if it is clear in the interface the ones removed--, I aim to remove stale incorrect information in comments that *all* users can see. Before continuing this conversation, you can quite easily look in your own answers for the pattern I try to avoid. – David Rodríguez - dribeas May 23 '11 at 12:13
  • @David: You said *"but you can go back to your answers, and **figure out how many of the comments left** in your modified answers are unrelated to the final version of your answer. I find that much more disturbing"*..........But that is **not** case here. Nobody has commented on your old post, and as you yourself said *"Once I realized the answer was wrong, I deleted it immediately"*, you could have posted the new content in the same post to avoid multiple posts. Your theory *many-comments-left-in-the-modified-answer* seems to be very unconvincing here. – Nawaz May 23 '11 at 12:19
  • @Nawaz: I highly value consistency, and following the same pattern under all circumstances, which in my case, for a wrong answer, is "delete answer, rethink and if there is a new answer, add it". Yes, in this particular case I could have used a shortcut: "delete contents, rethink, if there is a new answer post it". Note that there is an important "rethink" in between. If I had left the answer as it was, I might have gotten comments pointing at the fact that it did not answer the question. – David Rodríguez - dribeas May 23 '11 at 14:18
  • [cont'd] If I had deleted the contents (but not the answer) then I might have gotten comments saying "wtf! what is an empty answer doing here?", both of those outcomes would then justify "deleting the answer" *then*. So why go through the whole process and not delete it in the first place? The simple solution is apply the same process in all cases: "delete, rethink, write new" to avoid having to "edit, rethink, edit, notice comment, delete, write new, argue *ad infinitum*" --oh, well, I did not manage the last part, and here we are arguing *ad infinitum*... – David Rodríguez - dribeas May 23 '11 at 14:21
  • [cont'd] Seriously, I have better things to do than keeping this argument, I already said it: we have a different point of view, I am for sure not going to convince you, and I have had to revisit the list of editions in some answers to try and figure what the comments mean (in particular that seems to be far more common in your answers than anybody else's). I find that much worse than having a greyed out answer at the very end of the list. (Common, what is the actual problem with *ignoring* anything that is greyed out! Is it that hard?) :) – David Rodríguez - dribeas May 23 '11 at 14:24
  • @David: If you had deleted the contents but not the answer? See you're making it complicate, even though it is not. How about "after deleting the answer/post, erase the content, write the new answer, and then undelete the answer"? After deleting the post, nobody can comment it. – Nawaz May 23 '11 at 14:25
  • @David: No hard. But think if everybody follows this pattern of yours, there will be 2,3,4, even 5 posts, per user, even though only one of them is visible to ALL, and others (the deleted ones) will be visible to us only. – Nawaz May 23 '11 at 14:27
  • Seriously, I can but remember a quote that one professor once told me: *arguing with an engineer is like mud wrestling with a pig, sooner or later you realize they are enjoying it*. Now, first example: http://stackoverflow.com/questions/5772298/creating-an-integernumber-class-for-a-homework-assignment-in-c-to-sum-large-int/5772329#5772329... do you have a history of long discussions or what? But at any rate: how many of those comments apply to the answer as shown? I have better things to do than this useless argument. You don't like the greyed answer at the end, I don't like the linked answer. – David Rodríguez - dribeas May 23 '11 at 14:37
  • @David: You're pushing this from one end to the other deliberately. How does it apply here? Who have commented on your old post? None. – Nawaz May 23 '11 at 14:40
  • I give up :), I just got tired of the whole discussion. You do realize that the fact that I deleted the post can be a cause to the fact that there are no comments, don't you? – David Rodríguez - dribeas May 23 '11 at 15:15
  • 1
    @David: Yes. And that is the very thing I'm saying. After deleting the post you can edit it, re-edit it, thousands of times, and once you're done, you can again undelete it so that others can see it. I think it avoids unnecessary new post. – Nawaz May 23 '11 at 15:17
  • 1
    I agree with David. It's a completely separate answer, that should have a new post date, reset votes, no comments. I understand the re-use principle and sometimes it fits, but people re-using questions and answers by completely changing them through edits is downright irritating. – Lightness Races in Orbit May 31 '11 at 08:40
1

My crystal ball tells me that you are somehow transmogrifying the class name you retrieve from the type_info, as this name is not directly a class name, but rather an implementation-defined string that is sufficiently derived from the class name to allow equality comparison, and that in that process, both names are mapped to "MyClass" (i.e. you are cutting off the inner class's name), hence both end up in the same handler.

If you want to compare types at runtime, compare the type_info nodes directly:

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

If you have a closed list of types you handle in method (and in your implementation, there is, because you cannot add more cases to a list of chained if statements), there is no real reason to use a template; a regular overload is enough:

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;
        // ...
    }
    // ...
};
Simon Richter
  • 28,572
  • 1
  • 42
  • 64
  • While OP's method of using typeid is wrong and ridiculous, it's *not* the source of the error, because the code fails to *compile* and typeid is runtime thing. – Jan Hudec May 23 '11 at 09:49
  • +1 though, because this *is* how the code should have looked in the first place. – Jan Hudec May 23 '11 at 09:52
  • ... oh, `MyClass *copy = new MyClass(obj)` would do it some justice too. – Jan Hudec May 23 '11 at 09:59
  • i don't know how to solve the error i did edit the code.need some help:) – marryy May 23 '11 at 12:01
  • As @jan said, *typeid* is the wrong approach here, I mentioned it mainly for completeness. Read the rest of my answer. – Simon Richter May 23 '11 at 12:07
  • Using a *dynamic_cast* doesn't make sense here either, it just works around the fundamental problem. – Simon Richter May 23 '11 at 13:19
  • Reinterpreting the original question: do you perhaps want to do the same thing for all classes given to the method? In that case, a template would indeed be the way to go: `template bool method(T &obj) { T *copy = new T; *copy = obj; /* ... */ }` – Simon Richter May 23 '11 at 13:30