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

Thread: Is this guaranteed to be correct?

  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
    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 !? )

  4. #4
    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

  5. #5
    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.

  6. #6
    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

  7. #7
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    6,768

    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

  8. #8
    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

  9. #9
    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 )

  10. #10
    Join Date
    Jul 2013
    Posts
    576

    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 it's clear.

    The type_index was introduced as a unique identifier of a type_info (since the hash_code didn't serve this purpose).

    Furthermore the hash_code of a type_info is the same as the hash_code of a type_index of the same type_info.

  11. #11
    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.

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

    Re: Is this guaranteed to be correct?

    Actually the implementation has a lot of type safety. That was one of the goals I had in mind.

    I have static asserts that will ensure a compile error if an unsupported type is requested.
    Code:
    int i;
    i = variant.Get<int>(); // This will fail to compile if 'variant' does not support 'int'.
    i = int(variant);       // This will fail to compile if 'variant' does not support 'int'.
    variant = i;            // This will fail to compile if 'variant' does not support 'int'.
    An exception will be thrown if the type requested is supported but not the currently stored type.
    Code:
    double d;
    variant = 1;               // 'int' & 'double' supported.
    d = variant;               // Throw exception.
    d = variant.Get<double>(); // Throw exception.
    It implements a build-in visitor base class that allows type safe callbacks.
    Code:
    class Reader : public Variant<char, int>::Reader
    {
    public:
      void Read(int i)  { }
      void Read(char c)  { }
    };
    
    Reader reader;
    
    variant.Call(reader);
    "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

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

    Re: Is this guaranteed to be correct?

    Since you only seem to be concerned about static types... (#6) and both the samples in #1 and #2 seem to confirm this.
    Why aren't you using static (compile time) verifications between the types ? Should be fairly easy to implement, and the advantage is that it takes NO extra code to be executed (though it will burden the compiler a bit), the test will simply result in a static true/false constant. If would allow both runtime tests (as in #1) as well as compile time tests and static_assert()s.

    The only way that could not be the case is if you are indeed using the types dynamically through a base class and passing base pointers/references around and then trying to upcast them back to the original type (=a bad idea since that probably takes a huge switch or if/else cascade. If so, there is probably a better solution to the design if this is the case).

    Also, I'm not 100% sure the id's will be guaranteed identical for types originating from separately compiled units. I'm having a suspicion it'll generate different id's for identical types in different modules. A smart linker might resolve that anyway, but then we're entering the 'compiler/linker dependant' behaviour' dilemma. Again, this may not be an issue to you.

    Imo, the attempt to try and get a static typing identification based on a dynamically generated type id is "asking for problems somewhere down the road", especially if you want this to be portable. Again, may not be an issue to you.

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

    Re: Is this guaranteed to be correct?

    The code below will work for (typed) variables. It can't work entirely static since variables never are, only types are.
    the alternative is to call std::is_same directly if you have a type.

    Code:
    #include <type_traits> 
    
    template <class first, class second>
     bool sametype(const first& /*f*/, const second& /*s*/) 
    {
    	return std::is_same<first, second>::value;
    }
    
    int main()
    {
    	any<int, int, double> iid1;
    	any<int, int, double> iid2;
    	any<int, double, double> idd;
    
    	bool b1 = sametype(iid1,iid2); // true
    	bool b2 = sametype(iid1,idd); // false
    }
    depends a bit on your compiler, but it'll pretty much result in a static true/false, or at worse in a call to a function returning true or false.

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

    Re: Is this guaranteed to be correct?

    Your example isn't solving the same problem as what I was describing.

    What I my class is designed to do is this.
    (Types in the template parameter list must be unique; no duplicates)

    Code:
    int main()
    { 
      any<int, char, double> icd1; 
      any<int, char, double> icd2; 
    
      icd1 = 1; // Assign an int.
      icd2 = 2; // Assign an int.
    
      bool b1 = icd1.IsSameTypeAs(icd2); // true
    
      icd1 = 2.2; // Assign a double.
    
      bool b2 = icd1.IsSameTypeAs(icd2); // false
    }
    "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 4 1234 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
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width




On-Demand Webinars (sponsored)