Limiting function input only to __int64 but not int...

Discussion in 'C++' started by A, Oct 23, 2011.

  1. A

    A Guest

    Is there a way (except overloading) to limit function input to accept
    __int64 but to get a compiler (preferable) or runtime (less preferable)
    error if it is called with int?

    for example:

    void myfunction(__int64 param) // Accepts only __int64 as input and no
    smaller
    {
    }

    myfunction((__int64)1); // Call OK
    myfunction((int)1); // Call fails or better - compiler reports error
     
    A, Oct 23, 2011
    #1
    1. Advertisements

  2. A

    Ian Collins Guest

    You can use a function template to force a link error:

    #include <stdint.h>

    template <typename T> void f( T n );

    template <> void f( int64_t n ) // Specialise for acceptable types
    {
    }

    Or give the function template a body to force a compiler warning:

    template <typename T> void f( T n )
    {
    T tmp = n/0;
    }
     
    Ian Collins, Oct 23, 2011
    #2
    1. Advertisements

  3. A

    Marc Guest

    Assuming that __int64 is not the same type as int.

    with overloading (what's wrong with overloading?):
    void f(long){}
    void f(int)=delete;

    with sfinae:
    template<class T,class=typename std::enable_if<std::is_same<T,long>::value>::type> void f(T){}
     
    Marc, Oct 23, 2011
    #3
  4. A

    A Guest

    Thank you for your answers so far. I was hoping though for something without
    templates. I did found though BOOST_STRONG_TYPEDEF which pretty much does
    this.
     
    A, Oct 24, 2011
    #4
  5. A

    Goran Guest

    Out of curiosity... Why? int "is an" __int64 any way you look at this.
    Why would it matter?

    Goran.
     
    Goran, Oct 24, 2011
    #5
  6. void myfunction(const __int64& param);


    Marcel
     
    Marcel Müller, Oct 24, 2011
    #6
  7. A

    Ian Collins Guest

    Won't the normal promotion rules still apply?

    myfunction( 2 );

    Compiles happily as does

    int n = 0;
    myfunction( n );
     
    Ian Collins, Oct 24, 2011
    #7
  8. A

    Ian Collins Guest

    Hit send too soon, I was going to add that

    void myfunction( int64_t& param );

    was probably what you intended to type.
     
    Ian Collins, Oct 24, 2011
    #8
  9. I don't think that's a very good idea.
     
    Juha Nieminen, Oct 24, 2011
    #9
  10. A

    none Guest

    A compile time assertion would be a bit safer.
     
    none, Oct 24, 2011
    #10
  11. A

    A Guest

    because function requires explicitly __int64 because ID's are 64-bit,
    providing 32-bit int would ruin ID's that go over the 32-bit boundary. This
    may happen when I do text-to-int conversions using StrToInt and forget to
    put StrToInt64 instead.

    In Borlangearcadero C++ Builder 2010 which I use, these functions output int
    and __int64 so compiler SHOULD be able to check these but unfortunately it
    doesn't - even if I enable W8102 Implicit conversion of '%s' to '%s' (C++)
    but it doesn't do what it is supposed to. I tried casting to wrong type but
    the warning is still not triggered.
     
    A, Oct 24, 2011
    #11
  12. Actually, once you define one disallowed form, the rest become
    ambiguous. For example, calling with a "short" neither short->int or
    short->__int64 has a preference, so I believe it should give an error. I
    don't think the =delete removes that version from overload resolution,
    but I haven't looked at it in detail yet.
     
    Richard Damon, Oct 24, 2011
    #12
  13. A

    A Guest

    I actually like this solution but the compiler doesn't support it. I guess
    I'll be looking for alternate solutions.
     
    A, Oct 24, 2011
    #13
  14. if it doesn't support the =delete syntax, declaring (but not defining)
    void f(unsigned char); (choose an integer type that you are actually
    unlikely to mistakenly use) will make a call of f(1) ambiguous and thus
    an error. You want to make the undefined type an unlikely mistake as if
    you use it by mistake, you are just going to get a link error, and you
    will have to search to find where it is actually called.
     
    Richard Damon, Oct 25, 2011
    #14
  15. A

    Arne Mertz Guest

    #pragma error is not very portable, e.g. MSVC does not
    sopport it, instead, it issues a warning about the
    unsupported pragma and happily continues compiling,
    i.e. f(int) may be called.

    overloading f(int) and f(__int64) imo is not a good idea,
    because once you port the whole thing to a 64 bit machine
    int and __int64 become the same and you get either a
    redefinition error (if you actually defined f(int)), or
    the whole "error detection via link error or ambiguity"
    magically dissapears if you only declared f(int), as it
    is just another declaration of f(__int64).
    In your case the latter behavior may be ok, if the
    problem is only about disambiguating 32 bit int and __in64
    in 32 bit systems. But maybe StrToInt outputs __int32
    even on 64 bit systems or something similar happens so you
    want to keep up the 32 bit integer detection even on 64 bit
    systems.

    To make things short(er), I would use overloading, but not
    with any specific integer type but with a template:
    given f(__int64) as the function to be called only for
    64bit types, you have several variants

    Variant a)
    template <typename T>
    void f(T) = delete; //overload resolution calls this for
    any T that is not the same as __int64

    Variant b), C++0x without deleted functions
    template <typename T>
    void f(T)
    { static_assert(false, "call f only with __int64!"); }

    Variant c), C++0x, less restrictive
    #include <type_traits>
    template <typename T>
    f(T t) -> decltype(f(__int64))
    {
    // assert T is "sufficiently close to" __int64
    static_assert(std::is_integral<T>::value
    && std::is_convertible<T, __int64>::value
    && sizeof(T) >= sizeof(__int64));

    return f(__int64(t));
    }

    If your compiler lacks support for static_assert, you
    could use either std::enable_if or the STATIC_ASSERT
    macro from the loki library. If your standard library
    has no <type_traits>, boost provides similar utilities.

    HTH Arne
     
    Arne Mertz, Oct 26, 2011
    #15
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.