NOTE. I added a similar but significantly simplified version of the problem to the ambiguous overload of functions such as `msg (long)` using ms # int32_t) `and` msg (int64_t) ` . This version has the advantage of a complete compiled example in a single file.
Problem
I have a C library with features like
obj_from_int32(int32_t& i); obj_from_int64(int64_t& i); obj_from_uint32(uint32_t& i); obj_from_uint64(uint64_t& i);
In this case, the types are int32_t , etc. are not std tags - they are defined in the implementation, in this case an array of characters (in the following example, I omitted the conversion - it does not change the question regarding the comparison of intergroup types with a specific function based on the number of bits in the integral type).
I have a second class C ++ interface that has constructors like
MyClass(int z); MyClass(long z); MyClass(long long z); MyClass(unsigned int z); MyClass(unsigned long z); MyClass(unsigned long long z);
Note, I cannot replace this interface with styles like std::int32_t - if I could not ask this question;)
The problem is how to call the correct obj_from_ function based on the number of bits in the integral type.
Suggested Solutions
I put the two solutions proposed, since not one solution for the killer has moved to the top of the list, and there are some that have been broken.
Solution 1
Greetings and hth provided. - Alf . The comments from this paragraph are my own - feel free to comment and / or edit.
Advantages - Pretty simple (at least compared to boost::enable_if ) - Doesn't rely on a third-party library (as long as the compiler supports tr1 )
* Disadvantages ** - If more functions are required (e.g. anotherObj_from_int32 etc.), much more code is required
This solution can be found below - look, it's elegant!
Decision 2
Benefits
After executing the ConvertFromIntegral functions, adding new functions that require conversion is trivial - just write a set overloaded with int32_t , int64_t and unsigned equivalents.
Saves templates in only one place; they do not spread as the method is reused.
disadvantages
- Perhaps too complicated using
boost::enable_if . To some extent, the fact that this appears in only one place is mitigated.
Since this is mine, I canโt accept it, but you can transfer it if you think itโs neat (and, obviously, some people donโt think that it is incompatible, which, it seems to me, reduces it) Thank you to everyone who contributed ideas!
The solution includes a conversion function from int , long and long long to int32_t and int64_t (and similar for unsigned versions). This is combined with another set of functions overloaded with int32_t , int64_t and unsigned equivalents. The two functions can be combined, but the first conversion functions make a convenient set of utilities that can be reused, and then the second set of functions is trivially simple.
// Utility conversion functions (reuse wherever needed) template <class InputT> typename boost::enable_if_c<sizeof(InputT)==sizeof(int32_t) && boost::is_signed<InputT>::value, int32_t>::type ConvertFromIntegral(InputT z) { return static_cast<int32_t>(z); } template <class InputT> typename boost::enable_if_c<sizeof(InputT)==sizeof(int64_t) && boost::is_signed<InputT>::value, int64_t>::type ConvertFromIntegral(InputT z) { return static_cast<int64_t>(z); } template <class InputT> typename boost::enable_if_c<sizeof(InputT)==sizeof(uint32_t) && boost::is_unsigned<InputT>::value, uint32_t>::type ConvertFromIntegral(InputT z) { return static_cast<uint32_t>(z); } template <class InputT> typename boost::enable_if_c<sizeof(InputT)==sizeof(uint64_t) && boost::is_unsigned<InputT>::value, uint64_t>::type ConvertFromIntegral(InputT z) { return static_cast<uint64_t>(z); } // Overload set (mock implementation, depends on required return type etc) void* objFromInt32 (int32_t i) { obj_from_int32(i); } void* objFromInt64 (int64_t& i) { obj_from_int64(i); } void* objFromUInt32(uint32_t& i) { obj_from_uint32(i); } void* objFromUInt64(uint64_t& i) { obj_from_uint64(i); } // Interface Implementation MyClass(int z) : _val(objFromInt(ConvertFromIntegral(z))) {} MyClass(long z): _val(objFromInt(ConvertFromIntegral(z))) {} MyClass(long long z): _val(objFromInt(ConvertFromIntegral(z))) {} MyClass(unsigned int z): _val(objFromInt(ConvertFromIntegral(z))) {} MyClass(unsigned long z): _val(objFromInt(ConvertFromIntegral(z))) {} MyClass(unsigned long long z): _val(objFromInt(ConvertFromIntegral(z))) {}
A simplified (the only compiled .cpp !) Version of the solution is given in the ambiguous overload of functions such as `msg (long)` with candidates `msg (int32_t)` and `tz (int64_t)`