Мне нужна функция, которая может принимать любой тип аргумента, а затем в реализации может проверять, является ли тип целочисленным, а затем может выдавать сообщение. Например, функция может быть вызвана следующим образом:
add(10, 12);
Output : "correct input. addition is 22"
add(10, "hello")
Output : "wrong input"
add(10)
Output : "wrong input! missing arguments"
Можно ли добиться этого на С++?
Используя перегрузку, мне придется создавать функции всех возможных комбинаций, таких как (int, double), (double, int), (int, string), (string, int) и т. д., так есть ли другой способ?
Перегрузка кажется одним из возможных решений. Вместе с шаблонами. Но получение ошибки компилятора кажется гораздо более разумным решением.
Начиная с C++17, вы можете использовать std::any и std::any_cast:
#include <any>
#include <iostream>
void add(const std::any& a = "", const std::any& b = "")
{
try {
const int ia = std::any_cast<int>(a);
const int ib = std::any_cast<int>(b);
std::cout << "correct input. addition is " << ia + ib << std::endl;
}
catch (...) {
std::cout << "wrong input" << std::endl;
}
}
int main()
{
add(10, "hello");
add(10, 12);
add(10);
add();
}
Демо
Решение до С++ 17:
#include <iostream>
void add(int a, int b)
{
std::cout << "correct input. addition is " << a + b << std::endl;
}
template<typename... Ts>
void add(Ts...)
{
std::cout << "wrong input" << std::endl;
}
int main()
{
add(10, "hello");
add(10, 12);
add(10);
add();
}
Демо
Просто чтобы вы знали, я отклонил ваше редактирование, которое добавило тег C++ 17 к вопросу, потому что, хотя вы правы в том, что std::any требует C++ 17, вопрос не был ограничен этой редакцией и ответы использование более ранних/поздних версий должно быть разрешено. Как правило, теги версии языка не добавляются к вопросам C++ только потому, что в ответе используется определенная версия.
Чтобы избежать возникновения исключения, если вы, вероятно, его получите, вы также можете протестировать с помощью type() , который возвращает typeid содержащего элемента.
Первое, что нужно сделать, это написать перегрузку, которая принимает ровно 2 целых числа:
void add(int a, int b) {
std::cout << "Correct input. Answer is " << a + b << "\n";
}
И этого в целом должно быть достаточно. Если вызов сделан с неправильным количеством аргументов или с 2 аргументами, которые не могут быть преобразованы в int, компилятор выдаст вам ошибку.
Если вам не нужна ошибка, а вместо этого вы хотите распечатать сообщение об ошибке во время выполнения, вы можете просто добавить перегрузки. Как вы заметили, добавление перегрузок для явных типов на самом деле не сработает, но вы можете добавить общую функцию (шаблон функции), которая примет что угодно:
void add(auto ...) {
std::cout << "Incorrect input\n";
}
Обратите внимание, что до C++20 подпись должна быть написана по буквам
template<typename ...Ts>
void add(Ts ...);
Вы можете продолжать добавлять больше перегрузок, если вам нужны более конкретные сообщения об ошибках, например. для вызова, в котором передается только один аргумент:
void add(auto) {
std::cout << "Insufficient arguments\n";
}
Вот демо.
Можете ли вы объяснить, почему вы просто не определяете void add(int, int) и не позволяете компилятору выдавать ошибку? C++ — это язык со статической типизацией, и попытка подорвать систему типов — сложная тема. Смотрите также Шаблоны и std::any