Home > Net >  How to prevent floating-point being implicitly converted to integral value at function call in c ?
How to prevent floating-point being implicitly converted to integral value at function call in c ?

Time:11-04

How to prevent floating-point being implicitly converted to integral value at function call?

#include <iostream>

void fn(int x) {
    std::cout<<"fn("<<x<<")\n";
}

int main() {
    std::cout<<"Hello, this is 301014 :)\n";
    fn(2);
    fn(3.5);
    return 0;
}

Here the outputs are 2 and 3 respectively.
I am compiling with g -std=c 11 31014.cpp -o 31014 -v. And there is no mention of 3.5 being converted to 3.
Is there a way to prevent, or atleast detect, this?

Kindly help me out, please.

CodePudding user response:

There are multiple ways to handle this in .

Method 1: You SFINAE the function template fn by using std::enable_if.

template<typename T>
typename std::enable_if<std::is_same<T, int>::value>::type fn(T x) {
    std::cout << "fn(" << x << ")\n";
}

int main() {
    std::cout << "Hello, this is 301014 :)\n";
    fn(2);       // works
    // fn(3.5);  // won't work;
}

Demo


Method 2: Alternatively, delete the functions using =delete, which shouldn't take place in template deduction.

void fn(int x) {                          // #1
    std::cout << "fn(" << x << ")\n";
}
template<typename T> void fn(T) = delete; // #2

int main() {
    std::cout << "Hello, this is 301014 :)\n";
    fn(2);      // works  using #1
    // fn(3.5); // won't work since it uses #2
}

Demo

CodePudding user response:

Another way to solve this is to add template<typename T> void fn(T)=delete; (also works with older c standards):

#include <iostream>

template<typename T> void fn(T)=delete;

void fn(int x) {
    std::cout<<"fn("<<x<<")\n";
}

int main() {
    std::cout<<"Hello, this is 301014 :)\n";
    fn(2);
    fn(3.5); // now gives error
    return 0;
}

CodePudding user response:

There are several ways to prevent implicit conversion.

  1. Using std::enable_if and std::is_same.

    template <class T, std::enable_if_t<std::is_same_v<T,int>,bool> = false>
    void func(T x) {
        cout << x << endl;   
    }
    
  2. In C 20, one can use requires

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

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

CodePudding user response:

Enable the right compiler warnings.

GCC and Clang call this warning -Wconversion.

With this flag, I get:

<source>:10:8: warning: implicit conversion from 'double' to 'int' changes value from 3.5 to 3 [-Wliteral-conversion]
    fn(3.5);
    ~~ ^~~
  • Related