CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 3 123 LastLast
Results 1 to 15 of 49

Hybrid View

  1. #1
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Is this guaranteed to be correct?

    I thought I'd get others to check this over as I'm not totally convinced that this is guaranteed to work in all cases.

    I have code that generates a unique id for a type. All code in all translation units must receive the same type id for a particular type.

    In a .cpp file I have:-
    Code:
    uint8_t NextUniqueId()
    {
      static uint8_t uniqueId(0);
      return uniqueId++;
    }
    This returns a new id for each call.

    In the .h file I have:-

    Code:
    template <typename T>
    uint8_t GetTypeIdFor()
    {
      static uint8_t id(NextUniqueId());
      return id;
    }
    This should return a unique id for a type.
    Code:
    unit8_t typeId = GetTypeIdFor<int>();
    My question:-
    If several cpp files include this header, will it be guaranteed that the returned ids for types will be identical across all translation units?

    My concern is that different translation units may have their own copy of 'GetTypeIdFor<int>' possibly resulting in non-identical type ids.

    Thoughts?
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

  2. #2
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: Is this guaranteed to be correct?

    Some background to the problem.

    I'm experimenting with a class similar in some ways to Boost::any, but more resource and performance friendly to our embedded platform.

    It's implemented as a sort of 'enhanced' union where the id of the current type is stored internally.

    Example
    Code:
    Any<char, short, int> any1;
    Any<char, short, int> any2;
    Any<int, std::string> any3;
    
    any1 = 1;
    any2 = 2;
    any3 = 3;
    
    any1.IsSameTypeAs(any2); // Should be 'true'.
    any1.IsSameTypeAs(any3); // Should be 'true'.
    Where 'IsSameTypeAs' compares the internal type ids.

    This should be true regardless of where the 'Any' instances are defined or declared.
    Last edited by JohnW@Wessex; August 26th, 2014 at 04:49 AM.
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

  3. #3
    Join Date
    Jul 2013
    Posts
    576

    Re: Is this guaranteed to be correct?

    Quote Originally Posted by JohnW@Wessex View Post
    I'm experimenting with a class similar in some ways to Boost::any, but more resource and performance friendly to our embedded platform.
    That's not a very good idea. It just encourages a non type safe usage of C++.
    Last edited by razzle; August 29th, 2014 at 12:56 AM.

  4. #4
    Join Date
    Jul 2013
    Posts
    576

    Re: Is this guaranteed to be correct?

    Quote Originally Posted by JohnW@Wessex View Post
    I'm experimenting with a class similar in some ways to Boost::any, but more resource and performance friendly to our embedded platform.
    Again, one of the most prominent characteristics of C++ is its type safety. It's amazing how much effort is spent on giving that away for nothing. It would be much better if all this effort went into making good solid designs instead.

    Boost::Any is a bad idea from start to finish. If people cannot design without downcasting then they should be forced to do so explicitly so it can be detected and corrected at the next code review. So for the sake of your platform I hope you drop this malign "feature".
    Last edited by razzle; August 29th, 2014 at 02:36 AM.

  5. #5
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: Is this guaranteed to be correct?

    Quote Originally Posted by razzle View Post
    Boost::Any is a bad idea from start to finish. If people cannot design without downcasting then they should be forced to do so explicitly so it can be detected and corrected at the next code review. So for the sake of your platform I hope you drop this malign "feature".
    yes, let's drop Any, and Variant and all of the technology like COM, C# VBS, javascript that depend on it !!!

    In a perfect utopic world, there is only 1 programming language, because there can be only one perfection. If there were two, than by it's very nature, one of the two would need to be less perfect and an abomination because of that. I don't know which language that perfect one is, but it definately won't be any in existance today.

    The real world is dirty, harsh, needs to deal with alls sorts of nasty, and sometimes, less than ideal designs get the job done adequately. Imo, there are much bigger design failures you could commit than something like this.

  6. #6
    Join Date
    Jul 2013
    Posts
    576

    Re: Is this guaranteed to be correct?

    Quote Originally Posted by OReubens View Post
    Imo, there are much bigger design failures you could commit than something like this.
    No! Trading away the type safety of C++ for reasons of programmer's convenience is a monumental blunder of almost biblical proportions. Static type checking is at the very foundation of C++. If you give it away the result is non-safe and inefficient code. It's not true C++ anymore.

    There are many languages that offer weaker and more dynamic typing than C++ so why is everybody so hellbent on violating C++ on every occasion? Pick another language for scripting or duck typing purposes for heavens sake. Please leave C++ alone.

    When ever you're downcasting, C++ puts a dunce cap on your head by forcing you to put in a dynamic_cast that stands out like a sore thumb. Hiding it in Boost::Any doesn't fool anyone. You're still wearing the dunce cap.

    Fortunately there seems to be strong resistance in the C++ Standards Committee against stupidities like Boost::Any so there's hope.
    Last edited by razzle; August 31st, 2014 at 11:43 PM.

  7. #7
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: Is this guaranteed to be correct?

    Quote Originally Posted by razzle View Post
    No! Trading away the type safety of C++ for reasons of programmer's convenience is a monumental blunder of almost biblical proportions.
    Part of the my personal design brief for my Variant class was to reduce any type safety issues to an absolute minimum. In this I think I've been pretty much successful. The main way to get around type safety would be to employ the same techniques you would use for any other type in C/C++; by brute force casting. Downcasting is completely unnecessary when using this class. In fact the internal mechanism employed only relies on upcasting to the base type. Any type of casting can be completely avoided by using the built-in type safe visitor base class.
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

  8. #8
    Join Date
    Oct 2008
    Posts
    1,456

    Re: Is this guaranteed to be correct?

    Quote Originally Posted by c++std
    If D is a template and is defned in more than one translation unit [...] If the defnitions of D satisfy all these requirements,
    then the program shall behave as if there were a single defnition of D. If the defnitions of D do not satisfy these requirements, then the behavior is undefned.
    the said requirements essentially being having the same tokens and resulting in the same name lookup ( that is true for your use case; pathologies may arise when T-dependent lookups kick in, like, say, if one includes different trait definitions/ADL activated functions or the like ).

    BTW, note that your code is not thread-safe.

    (ehy, is it just me, or the forum is slow as hell today !? )

  9. #9
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: Is this guaranteed to be correct?

    Thanks, that's good to hear.
    Our code is single threaded, though there are many interrupts.
    Thanks for reminding me about that.
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

  10. #10
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: Is this guaranteed to be correct?

    This will only ensure unique id's for a certain type, in so far as the type is static.
    for dynamic (anonymous) types, it'll keep generating new id's.
    if you are loading and unloading dll's using this, then it'll fail there as well.

    Also note that while a type may be static, it may not be uniquely instantiated. It is possible that the same type gets explicitely instantiated in every dll. (typical when using template types in multiple dll's).

    if you want to compare type equality, then you can do this via the RTTI system (as a general case), via template checks (for the static/compile time case), or via the new c++11 features (decltype, result_of(), typeof, ...)

    Also, your system may break for nested or inherited types, depending on how you were expecting them to behave.

  11. #11
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: Is this guaranteed to be correct?

    Quote Originally Posted by OReubens View Post
    This will only ensure unique id's for a certain type, in so far as the type is static.
    for dynamic (anonymous) types, it'll keep generating new id's.
    That's fine.

    if you are loading and unloading dll's using this, then it'll fail there as well.
    This is for an ARM based board with no OS, single threaded with a few interrupts, and a message passing cooperative scheduler.

    if you want to compare type equality, then you can do this via the RTTI system (as a general case), via template checks (for the static/compile time case), or via the new c++11 features (decltype, result_of(), typeof, ...)
    I couldn't find a way to use RTTI that didn't incur unacceptable time or space requirements.
    std::type_info was not really up to the job.
    dynamic_cast can't be used as the types can be unrelated.
    Our cross compiler does not support any C++11 features, and probably won't for some time.

    Also, your system may break for nested or inherited types, depending on how you were expecting them to behave.
    That's something I will have to add to the unit tests.
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

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

    Re: Is this guaranteed to be correct?

    Quote Originally Posted by JohnW@Wessex
    I couldn't find a way to use RTTI that didn't incur unacceptable time or space requirements.
    std::type_info was not really up to the job.
    As in the cost of typeid and conversion to std::type_index was too high?
    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

  13. #13
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: Is this guaranteed to be correct?

    Quote Originally Posted by laserlight View Post
    As in the cost of typeid and conversion to std::type_index was too high?
    Possibly. It's not clear what is going on behind the scenes. If it's just using the hash_code and the generation of the type_info is at compilation time then that would have been a perfect solution...except that it is C++11 only.

    One thing that concerned me about the hash_code is this paragraph from CPP Reference.

    Returns an unspecified value, which is identical for the type_info objects referring to the same type. No other guarantees are given.

    This seems to imply that the hash code may be shared by another type, which would make it useless for my needs anyway. Could std::type_index suffer the same problem? It's not clear.

    I think what I have is going to tick most of the boxes of a 'useful' variant type.
    That's the compromise you often have to make in the embedded world; A pragmatic decision based on getting the maximum number of useful features for the least cost.
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

  14. #14
    Join Date
    Oct 2008
    Posts
    1,456

    Re: Is this guaranteed to be correct?

    Quote Originally Posted by JohnW@Wessex View Post
    This seems to imply that the hash code may be shared by another type, which would make it useless for my needs anyway. Could std::type_index suffer the same problem? It's not clear.
    yes, the only goal of hash_code is to provide a good hash function for unordered containers, that is to provide uniformity and low ( but not zero ) collision probability.

    conversely, type_index ( and type_info ) must support "true" equality, in order to be properly used into associative containers.


    BTW, in "any1.IsSameTypeAs(any3);" given that you know both the type of any1 and any3 you could simply compare the index of the type as declared in the Any<> specialization, eg

    Any<char, short, int> defines a type map f1: char->0, short->1, int->2, let's call id1 the current id
    Any<int, std::string> defines a type map f2: int->0, string>1, let's call id2 the current id

    the two compare equal iff id1 == f1(f2^-1(id2)). So, no need of the GetTypeIdFor() machinery (unless I missed something )

  15. #15
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: Is this guaranteed to be correct?

    Quote Originally Posted by superbonzo View Post
    BTW, in "any1.IsSameTypeAs(any3);" given that you know both the type of any1 and any3 you could simply compare the index of the type as declared in the Any<> specialization, eg

    Any<char, short, int> defines a type map f1: char->0, short->1, int->2, let's call id1 the current id
    Any<int, std::string> defines a type map f2: int->0, string>1, let's call id2 the current id

    the two compare equal iff id1 == f1(f2^-1(id2)). So, no need of the GetTypeIdFor() machinery (unless I missed something )
    I've just realised the small, but significant difficulty with that method.

    Any<int, double> any1 = 1;
    Any<double, int> any2 = 1;

    bool b = any1.IsSameTypeAs(any2); // This will return 'false' despite both objects storing an 'int'.

    The purpose of GetTypeIdFor() is to always return the same id for a particular type.

    I could of course disallow comparison of types from different Any template declarations.
    This is probably a reasonable restriction to make in hind-site.
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

Page 1 of 3 123 LastLast

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