CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 14 of 14
  1. #1
    Join Date
    Aug 2009
    Posts
    23

    Template: great but now how do I detect type?

    Hi all,

    I used a template class to hold various types of data, for example:

    Code:
    struct Structure1
    {
    int a, b;
    }
    
    struct Structure2
    {
    char c, d;
    }
    
    
    template <class mytype> class CTheClass
    {
     ... 
    
    // This structure is different for every instance of this class because "mytype" can be Structure1 or Structure2
    typedef struct m_Class_Structure
    	{
    		vector <mytype> points;		
    	} m_Class_Structure;  
    }

    It was great and it saved me a lot of code.

    But now... how I detect if "mytype" is Structure1 or Structure2 ?

    I need to write code to handle specifically Structure1 and Structure2, and the code isn't the same for both.

    Any idea please?

  2. #2
    Join Date
    Sep 2004
    Location
    Holland (land of the dope)
    Posts
    4,123

    Re: Template: great but now how do I detect type?

    But now... how I detect if "mytype" is Structure1 or Structure2 ?
    You can't AFAIK.

    What I usually do is add a enum to the class/struct.

    Code:
    enum enmStructType {stStruct1, stStruct2};
    
    struct Structure1
    {
    enmStructType enType;
    
    int a, b;
    }
    
    struct Structure2
    {
    enmStructType enType;
    
    char c, d;
    }

  3. #3
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    6,765

    Re: Template: great but now how do I detect type?

    Quote Originally Posted by leKoxn
    But now... how I detect if "mytype" is Structure1 or Structure2 ?

    I need to write code to handle specifically Structure1 and Structure2, and the code isn't the same for both.

    Any idea please?
    Specialise the relevant function template(s) for Structure1 and Structure2.
    C + C++ Compiler: MinGW port of GCC
    Build + Version Control System: SCons + Bazaar

    Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
    Kindly rate my posts if you found them useful

  4. #4
    Join Date
    Apr 2008
    Posts
    725

    Re: Template: great but now how do I detect type?

    if you want to 'detect' type surely you could just try a dynamic cast? Having said that, I agree with laserlight's suggestion of specialisation as a better design.

    This isnt very good design imo, but I think it'll work:
    Code:
    CTheClass<Structure1> myClass;
    myClass.m_Class_Structure.points::value_type tempObj; // assuming m_Class_Structure is public or there is at least a const accessor.
    if( dynamic_cast<Structure2*>(&tempObj) )
    {
      // it's a Structure2
    }
    else if( dynamic_cast<Structure1*>(&tempObj) )
    {
      // it's a Structure1
    }
    Last edited by Amleto; April 25th, 2010 at 09:03 AM.

  5. #5
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    6,765

    Re: Template: great but now how do I detect type?

    Quote Originally Posted by Amleto
    if you want to 'detect' type surely you could just try a dynamic cast?
    Looking at leKoxn's example code, that will not work, since Structure1 and Structure2 are not polymorphic types.
    C + C++ Compiler: MinGW port of GCC
    Build + Version Control System: SCons + Bazaar

    Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
    Kindly rate my posts if you found them useful

  6. #6
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Template: great but now how do I detect type?

    Quote Originally Posted by leKoxn View Post
    But now... how I detect if "mytype" is Structure1 or Structure2 ?

    I need to write code to handle specifically Structure1 and Structure2, and the code isn't the same for both.
    Give us more information about the different code. What makes Structure1's code different than Structure2's code? Depending on this difference, there are various ways to solve this problem.

    One solution is to pass in another template class that gives the base template the different code. Then the base template just "calls" this code. This is called policy-based programming, and you can see it in action when you use std::string.

    A std::string is really a template defined something like this:
    Code:
    typedef std::basic_string<char, char_traits<char> > string;
    The second template parameter tells the basic_string template how to handle the "char" type for things such as comparisons, etc. This char_traits<> template is another struct with functions that the base template calls.

    If you look at std::wstring, it uses the same basic_string template, but the second parameter uses a different char_traits<>. So you have two different types, and the char_traits<> tells the template how to handle the type.

    Template specialization is another method of giving templates different behaviour, but if both Structure1 and Structure2 are basically the same thing except for a few differences, then maybe the policy-based approach is more viable.

    Regards,

    Paul McKenzie

  7. #7
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Template: great but now how do I detect type?

    Just to round out my last post, assume you have a template that takes a sequence based container, and you want to insert an item in the container. You don't know what the container is -- it could be a vector, list, an MFC CArray, CList, or someone's home-brewed sequence container, you don't know.

    So the problem is that you have this template, a container is passed to along with a value, and somehow you have to figure out how to insert this value into this container your template has no idea about. How would you solve this problem?

    Here is a proposed solution using the policy based approach:
    Code:
    #include <vector>
    #include <afxtempl.h>
    
    template <typename T>
    struct AdderTraits
    {
        template <typename U>
        static void AddElement(T& t, U& value)
        {
            t.push_back(value);
        }
    };
    
    // this one is for CArray
    template <typename T>
    struct CArrayAdderTraits
    {
        template <typename U>
        static void AddElement(T& t, U value)
        {
            t.Add(value);
        }
    };
    
    template <typename T, typename AddTraits = AdderTraits<T> >
    class Foo
    {
    public:
        T container;
        Foo() { }
        template <typename U>
        void AddElement(U value)
        {
            AddTraits::AddElement( container, value );
        }
    };
    
    int main()
    {
        typedef std::vector<int> IntVector;
        typedef CArray<double> DoubleCArray;
    
        Foo<IntVector> f1;
        Foo<DoubleCArray,  CArrayAdderTraits<DoubleCArray> > f2;
    
        f1.AddElement(10);  // Adds element 10 to the vector<int>
        f2.AddElement(20.0);  // adds element 20.0 to the CArray
    }
    By default, we do a push_back to add an element. If something different needs to be done, then we send a different traits to the Foo template, and that code is executed instead. Note that Foo has no idea what the container is -- all it knows is that the second template argument has an "AddElement()" function, and all Foo does is call this function. Note that there is no inheritance, no derivation, no virtual functions, etc. Another term used for this type of programming is compile-time polymorphism.

    Create an MFC console app and try the code above. It should compile and if you debug it, it shows you what is happening.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; April 25th, 2010 at 10:28 AM.

  8. #8
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: Template: great but now how do I detect type?

    Okay, here's what has me worried about this design:
    // This structure is different for every instance of this class because "mytype" can be Structure1 or Structure2
    Given that you only intend to instantiate this template with one of two types, and the behavior for those types is different......why are you using a template at all? What does it get for you?

    It may be the case that inheritance-based polymorphism is a better solution for this particular problem.

    I'm also wondering just how different the behavior is, which will greatly inform the appropriate solution.

  9. #9
    Join Date
    Aug 2009
    Posts
    23

    Re: Template: great but now how do I detect type?

    I just realized I should specializate EVERY type I use.

    It's stupid doing this, so I think I need to rewrite my entire project keeping one class for all instances...

    so I'm changing my question: What is the best way to write a class with optional data?

    For example:


    Code:
    class MySpecialClass
    {
    int normaldata;
    int data_presents_for_all_instances
    
    [ int This_data_should_be_present_just_for_some_instances]
    [ int This_data_too]
    
    
    }


    I almost forgot: thank you for all your help above, it wasn't wasted time because it helped me to get that my project has to be rewritten

  10. #10
    Join Date
    May 2007
    Location
    Scotland
    Posts
    1,164

    Re: Template: great but now how do I detect type?

    The most straight forward answer is to follow laserlights solution by template specialising the struct/class.

    However, Lindley has a point - it is possible that your design is just plain wrong. I can't comment on that though, since you haven't supplied enough information.

  11. #11
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    6,765

    Re: Template: great but now how do I detect type?

    Quote Originally Posted by leKoxn
    What is the best way to write a class with optional data?
    Why is the data optional? Have you considered the use of an inheritance hierarchy?
    C + C++ Compiler: MinGW port of GCC
    Build + Version Control System: SCons + Bazaar

    Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
    Kindly rate my posts if you found them useful

  12. #12
    Join Date
    Aug 2009
    Posts
    23

    Re: Template: great but now how do I detect type?

    The data are some kind of points calculated with algorithms.

    They all have coordinates, they all have a so-called descriptor... but some of them have additional data associated (10 doubles, 4 integers..)

    The hierarchy idea is good, but I need to access these structures in a simple way.

    Something like

    MYclass a;
    a.GetPoints();
    CalculateOtherData( a.RetrievePoints() );

  13. #13
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: Template: great but now how do I detect type?

    I suppose you could give the type all possible members, and then simply ignore the ones that aren't relevant to a given object.

  14. #14
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,633

    Re: Template: great but now how do I detect type?

    What is the best way to write a class with optional data?
    People call it inheritance. Base class contains mandatory data, and specific descendant appends optional data to it.

    Other solution could be an "open" structure (very unusual approach for C++):

    Code:
    class Base {
       // mandatory part
       BYTE appendix[1];
    };
    
    // Appendix must start with some structure id to let unambiguously cast 
    // the raw bytes tail to particular structure type at runtime


    But putting the question this way still cannot let you think it isn't something wrong with your general approach. Is it possible that your data so much irregularly polymorphic? If yes, you should think about packing it to XML.
    Best regards,
    Igor

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured