c++functioncastingimplicit-conversion

How do I avoid implicit conversions on non-constructing functions?


How do I avoid implicit casting on non-constructing functions?
I have a function that takes an integer as a parameter,
but that function will also take characters, bools, and longs.
I believe it does this by implicitly casting them.
How can I avoid this so that the function only accepts parameters of a matching type, and will refuse to compile otherwise?
There is a keyword "explicit" but it does not work on non-constructing functions. :\
what do I do?

The following program compiles, although I'd like it not to:

#include <cstdlib>

//the function signature requires an int
void function(int i);

int main(){

    int i{5};
    function(i); //<- this is acceptable

    char c{'a'};
    function(c); //<- I would NOT like this to compile

    return EXIT_SUCCESS;
}

void function(int i){return;}

*please be sure to point out any misuse of terminology and assumptions


Solution

  • 8 years later (PRE-C++20, see edit):

    The most modern solution, if you don't mind template functions -which you may mind-, is to use a templated function with std::enable_if and std::is_same.

    Namely:

    // Where we want to only take int
    template <class T, std::enable_if_t<std::is_same_v<T,int>,bool> = true>
    void func(T x) {
        
    }
    

    EDIT (c++20)

    I've recently switched to c++20 and I believe that there is a better way. If your team or you don't use c++20, or are not familiar with the new concepts library, do not use this. This is much nicer and the intended method as outlines in the new c++20 standard, and by the writers of the new feature (read a papers written by Bjarne Stroustrup here.

    template <class T>
        requires std::same_as(T,int)
    void func(T x) {
        //...
    }
    

    Small Edit (different pattern for concepts)

    The following is a much better way, because it explains your reason, to have an explicit int. If you are doing this frequently, and would like a good pattern, I would do the following:

    template <class T>
    concept explicit_int = std::same_as<T,int>;
    
    template <explicit_int T>
    void func(T x) {
    
    }
    

    Small edit 2 (the last I promise)

    Also a way to accomplish this possibility:

    template <class T>
    concept explicit_int = std::same_as<T,int>;
    
    void func(explicit_int auto x) {
    
    }