Как предотвратить неявное преобразование числа с плавающей запятой в целое значение при вызове функции?
#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;
}
Здесь выходов 2 и 3 соответственно.
Я компилирую с g++ -std=c++11 31014.cpp -o 31014 -v. И нет упоминания о преобразовании 3.5 в 3.
Есть ли способ предотвратить или хотя бы обнаружить это?
Пожалуйста, помогите мне, пожалуйста.





В c++11 есть несколько способов справиться с этим.
Способ 1: вы SFINAE шаблон функции fn с помощью 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;
}
Способ 2: В качестве альтернативы удалите функции с помощью =delete, чего не должно быть в
вычет по шаблону.
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
}
Другой способ решить эту проблему — добавить template<typename T> void fn(T)=delete; (также работает со старыми стандартами С++):
#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;
}
Это решение, которое я бы предпочел, потому что оно не заставляет меня реализовывать функцию, использующую int в качестве шаблона.
Есть несколько способов предотвратить неявное преобразование.
Использование std::enable_if и 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;
}
В C++ 20 можно использовать требует
template <class T>
requires std::same_as(T,int)
void func(T x) {
// ....
}
Использование концепции .
template <class T>
concept explicit_int = std::same_as<T,int>;
void func(explicit_int auto x) {
// ...
}
Включите правильные предупреждения компилятора.
GCC и Clang называют это предупреждение -Wconversion.
С этим флагом я получаю:
<source>:10:8: warning: implicit conversion from 'double' to 'int' changes value from 3.5 to 3 [-Wliteral-conversion]
fn(3.5);
~~ ^~~
-Wconversionили-Wfloat-conversionвыдаст вам предупреждение. gcc.gnu.org/onlinedocs/gcc/Warning-Options.html