Accept Any type of argument in cpp - c++

I want a function that can accept any type of argument and then in the implementation, can check if the type is integer and then can throw a message. For example the function can be called like the following,
add(10, 12);
Output : "correct input. addition is 22"
add(10, "hello")
Output : "wrong input"
add(10)
Output : "wrong input! missing arguments"
Is it possible to achieve this in C++?
Using overloading I will have to create functions of all possible combination such as (int, double), (double, int), (int, string), (string, int) and so on, so is there any other way?

Since C++17, you can use std::any and 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();
}
Demo
A pre-C++17 solution:
#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();
}
Demo

The first thing to do is write an overload that accepts exactly 2 ints:
void add(int a, int b) {
std::cout << "Correct input. Answer is " << a + b << "\n";
}
And that should generally be enough. If a call is made with an incorrect number of arguments, or with 2 arguments that can't be converted to int, the compiler will produce an error for you.
If you don't want an error, but instead want to print an error message at runtime, you can just add overloads. As you've noticed, adding overloads for explicit types isn't really going to work, but you can add a generic function (a function template) that will accept anything:
void add(auto ...) {
std::cout << "Incorrect input\n";
}
Note that pre-C++20, the signature has to be spelled
template<typename ...Ts>
void add(Ts ...);
You can continue adding more overloads if you want more specific error messages, e.g. for a call where only one argument is passed:
void add(auto) {
std::cout << "Insufficient arguments\n";
}
Here's a demo.

Related

Output a number that may be one of three types

I have a variable x.
It may either be of type char, uint8_t or std::string.
I wish to output the number (not character), using the same expression involving std::cout. This is because I use this expression in generated code.
At code-generation-time, I currently don't know if x will be char, uint8_t or std::string.
std::cout << x << std::endl does not work if x is of type char, since it will output the character and not the number.
std::cout << +x << std::endl does not work if x is of type std::string.
std::cout << (typeid(x) == typeid(uint8_t) || typeid(x) == typeid(char) ? +x : x) << std::endl does not work if x is of type std::string.
std::cout << (typeid(x) == typeid(uint8_t) || typeid(x) == typeid(char) ? static_cast<int>(x) : x) << std::endl does not work if x is of type std::string.
I am aware that std::cout can be configured in various ways by piping std::hex or std::boolalpha, but I know of no possible way to configure std::cout to output a char as a number, without casting the char first.
Is there a way to use reflection, operator overloading, templates or something else
so that one can have a single unified statement for outputting x, as a number?
For example, if x is 65 with type char, the desired output is 65, not A.
Just format a helper and specialize the versions you want to customize appropriately. For example:
#include <iostream>
template <typename T>
struct formatter {
T const& value;
};
template <typename T>
formatter<T> format(T const& value) {
return formatter<T>{value};
}
template <typename T>
std::ostream& operator<< (std::ostream& out, formatter<T> const& v) {
return out << v.value;
}
std::ostream& operator<< (std::ostream& out, formatter<char> const& v) {
return out << int(v.value);
}
template <std::size_t N>
std::ostream& operator<< (std::ostream& out, formatter<char[N]> const& v) {
return out << '\'' << v.value << '\'';
}
int main() {
std::cout << "char=" << format('c') << " "
<< "int=" << format(17) << " "
<< "string=" << format("foo") << " "
<< "\n";
}
I guess you are working within generic context. So your basic problem is that you need static dispatch. The trigraph operator ? : does not provide this. it is evaluated at run time and will always invoke the same operator<<.
So you have two options:
use a helper class with partial specialization.
use static if. I.e.:
if constexpr (std::is_integral<decltype(x)>::value)
std::cout << static_cast<int>(x) << std::endl;
else
std::cout << x << std::endl;
The latter requires C++17.
This solution worked for me. It outputs the char as a number by using the output function together with template specialization and if constexpr:
#include <cstdint>
#include <iostream>
#include <string>
using namespace std::string_literals;
template <typename T> void output(std::ostream& out, T x)
{
if constexpr (std::is_integral<decltype(x)>::value) {
out << static_cast<int>(x);
} else {
out << x;
}
}
int main()
{
char x = 65;
uint8_t y = 66;
std::string z = "hi"s;
// output: A
std::cout << x << std::endl;
// output: 65
output(std::cout, x);
std::cout << std::endl;
// output: B
std::cout << y << std::endl;
// output: 66
output(std::cout, y);
std::cout << std::endl;
// output: "hi"
output(std::cout, z);
std::cout << std::endl;
return 0;
}
Thanks to Dietmar Kühl and Marcel for the helpful answers.

Passing null string to function as an argument

What is the right way of passing NULL string to a function without creating a variable?
I see compilation error with following code and I don't want to change the definition. Also may have to make change to string so don't want to mark it a constant type.
#include <iostream>
#include <string>
using namespace std;
void
myfunc(int i, string &my) {
if (my.empty()) {
cout << "Empty" << endl;
} else {
cout << "String is " << my <<endl;
}
}
int main ()
{
std::string str1 ("Test string");
myfunc(1, str1);
std::string str2 ("");
myfunc(2, "");
return 0;
}`
my1.cpp:18: error: invalid initialization of non-const reference of type ‘std::string&’ from a temporary of type ‘const char*’
my1.cpp:6: error: in passing argument 2 of ‘void myfunc(int, std::string&)
’
Following compiles but I dont want to create local variable
#include <iostream>
#include <string>
using namespace std;
void
myfunc(int i, string &my) {
if (my.empty()) {
cout << "Empty" << endl;
} else {
cout << "String is " << my <<endl;
}
}
int main ()
{
std::string str1 ("Test string");
myfunc(1, str1);
std::string str2 ("");
myfunc(2, str2);
return 0;
}
The solution here is to have an overload that doesn't have the string parameter.
void myfunc(int i, string &my) {
cout << "String is " << my <<endl;
}
void myfunc(int i) {
cout << "Empty" << endl;
}
int main ()
{
std::string str1 ("Test string");
myfunc(1, str1);
myfunc(2);
}
This is the most simple and clear solution that conveys exactly your intent and functionality.
You shouldn't try to do it your way because if you want to modify the argument then the parameter should be "non-const reference" and so it cannot bind to temporaries. Thus you can't pass a string literal to it.
If you want to make it explicit that you don't pass a string, you could create a tag ala nullptr, although I do not recommend the extra complication when the above variant is clear and understood by everybody at first glance.
struct no_string_tag_t {};
constexpr no_string_tag_t no_string_tag;
void myfunc(int i, string &my) {
cout << "String is " << my <<endl;
}
void myfunc(int i, no_string_tag_t) {
cout << "Empty" << endl;
}
int main ()
{
std::string str1 ("Test string");
myfunc(1, str1);
myfunc(2, no_string_tag);
}
If you really want a single function, then the semantically correct version would have an optional reference.
auto foo(int i, std::optional<std::reference_wrapper<std::string>> my)
{
if (my)
cout << "String is " << my <<endl;
else
cout << "no string" << endl;
}
int main ()
{
std::string str1 ("Test string");
myfunc(1, str1);
myfunc(2, std::nullopt);
}
If you want to keep the function signature and still be able to pass it a temporary, then you are out of luck. C++ has a safety feature in that it does not allow a non-const lreferece to bind to a temporary. The reason for this restriction is that attempting to modify a temporary via a lreference would most likely be bug and not the programmers's intent since the temporary dies out anyway.
You can't pass a temporary to a non-const reference parameter. The object, being temporary, will be destroyed as soon as the function returns. Any changes that the function did to the object would be lost.
If you want to have the chance to modify the string, you can take the string by const reference and return a modified string.
string myfunc( int i, string const &s );
:
str1 = myfunc( 1, str1 );
auto result2 = myfunc( 2, "" );
Your other option is to use a pointer to a string that can be null.
void myfunc( int i, string *s ) {
if (!s) {
cout << "Empty" << endl;
} else {
cout << "String is " << *s <<endl;
}
}
myfunc( 1, &str1 );
myfunc( 2, nullptr );
You can ommit 1 or more arguments in functions calls as long those argument(s) are the last ones in the order or the args prototyped in that function.
You can also give a padron value if the argument is ommited when calling the function.
using namespace std;
void sTest(int a, string x ="TEST", int z=0);
void sTest(int a, string x, int z)
{
cout << x;
}
int main()
{
sTest(5); // displayed “TEST”
}

CLang LibTooling handling function Template arguments

I want to handle template arguments diffrently so for the code:
template <class T> class A {
public:
A() {}
};
void faa(A<int>& param);
I would like to know that param is a template specialisation and get access it's parameters.
So I wrote an ASTVisitor with function
bool VisitFunctionDecl(FunctionDecl *f) {
std::cout<< "VisitFunctionDecl" <<std::endl;
const DependentTemplateSpecializationType* t1;
const TemplateSpecializationType* t2;
for(ParmVarDecl* p :f->params())
{
t1=p->getType()->getAs<DependentTemplateSpecializationType>();
t2=p->getType()->getAs<TemplateSpecializationType>();
if(t1!=nullptr||t2!=nullptr)
{
std::cout<< "template param found" <<std::endl;
}
}
return true;
}
But those casts are both nullptr always - I never get the template param found output.
What am I doing wrong? Is there any other way to cast t to some king of type allowing checking of the template parameters?
Type of A<int>& is LValueReference (can be checked with getTypeClassName()). What you are probably trying to get is type pointed by reference. You can get it with getNonReferenceType() method.
bool VisitFunctionDecl(FunctionDecl *f) {
llvm::errs() << "VisitFunctionDecl:" << f->getQualifiedNameAsString()
<< "\n";
for (ParmVarDecl* p : f->params()) {
llvm::errs() << p->getType().getAsString() << " -> "
<< p->getType()->getTypeClassName() << "\n";
llvm::errs() << "isPointerType: "
<< p->getType()->hasPointerRepresentation() << "\n"
<< "isTemplateSpecialization: "
<< (nullptr != p->getType().getNonReferenceType()->getAs<
TemplateSpecializationType>()) << "\n";
}
return true;
}
output is:
VisitFunctionDecl:faa
const A<int> & -> LValueReference
isPointerType: 1
isTemplateSpecialization: 1

passing primitive data type to a function in c++

I want to implement a function like this
double d = string_to("1223.23",double);
int i = string_to("1223",int);
bool d = string_to("1",bool);
How can I pass the bool, int, double data type to implement this in c++?
Types line int, double and bool can only be passed as template parameters.
You can use templates like this:
#include <string>
#include <sstream>
#include <iostream>
template<typename DataType>
DataType string_to(const std::string& s)
{
DataType d;
std::istringstream(s) >> d; // convert string to DataType
return d;
}
int main()
{
double d = string_to<double>("1223.23");
int i = string_to<int>("1223");
bool b = string_to<bool>("1");
std::cout << "d: " << d << '\n';
std::cout << "i: " << i << '\n';
std::cout << "b: " << b << '\n';
}
As an alternative you can pass your numeric types by reference and rely on function overloading to select the correct function:
void string_to(const std::string& s, double& d)
{
d = std::stod(s);
}
void string_to(const std::string& s, int& i)
{
i = std::stoi(s);
}
void string_to(const std::string& s, bool& b)
{
std::istringstream(s) >> std::boolalpha >> b;
}
int main()
{
double d;
int i;
bool b;
string_to("1223.23", d);
string_to("1223", i);
string_to("true", b);
std::cout << "d: " << d << '\n';
std::cout << "i: " << i << '\n';
std::cout << "b: " << b << '\n';
}
Also you could templatize the second method (an exercise for the reader).
If you really want to do this, you can pass the type by using the typeid operator.
E.g. double d = string_to("1223.23", typeid(double));
Using the library functions atoi, stod would make more sense.
If you're aiming to write more uniform code then you could write a Converter object and use method overloading to get automatic selection by type.
class Converter
{
public:
void fromString(double& value, const char* string);
void fromString(int& value, const char* string);
void fromString(long& value, const char* string);
};
Here's another way that uses tag dispatching. You can compile and run this example.
#include <iostream>
#include <string>
#include <cmath>
namespace detail {
// declare the concept of conversion from a string to something
template<class To>
To string_to(const std::string&);
// make some models of the concept
template<>
int string_to<int>(const std::string& s) {
return atoi(s.c_str());
}
template<>
double string_to<double>(const std::string& s) {
return atof(s.c_str());
}
template<>
std::string string_to<std::string>(const std::string& s) {
return s;
}
// ... add more models here
}
// define the general case of conversion from string with a model tag
// note the unused parameter allows provision of a model that is never used
// thus the model will in all likelihood be optimised away
template<class To>
To string_to(const std::string& from, const To& /* model_tag is unused */)
{
// dispatch to correct conversion function using the To type
// as a dispatch tag type
return detail::string_to<To>(from);
}
using namespace std;
int main()
{
// examples
int a = string_to("100", a);
double b = string_to("99.9", b);
const string s = string_to("Hello", s);
cout << s << " " << a << " " << b << endl;
return 0;
}
output:
Hello 100 99.9

Dynamically creating a C++ function argument list at runtime

I'm trying to generate an argument list for a function call during runtime, but I can't think of a way to accomplish this in c++.
This is for a helper library I'm writing. I'm taking input data from the client over a network and using that data to make a call to a function pointer that the user has set previously. The function takes a string(of tokens, akin to printf), and a varying amount of arguments. What I need is a way to add more arguments depending on what data has been received from the client.
I'm storing the functions in a map of function pointers
typedef void (*varying_args_fp)(string,...);
map<string,varying_args_fp> func_map;
An example usage would be
void printall(string tokens, ...)
{
va_list a_list;
va_start(a_list, tokens);
for each(auto x in tokens)
{
if (x == 'i')
{
cout << "Int: " << va_arg(a_list, int) << ' ';
}
else if(x == 'c')
{
cout << "Char: " << va_arg(a_list, char) << ' ';
}
}
va_end(a_list);
}
func_map["printall"] = printall;
func_map["printall"]("iic",5,10,'x');
// prints "Int: 5 Int: 10 Char: x"
This works nicely when hardcoding the function call and it's arguments, but if I've received the data "CreateX 10 20", the program needs to be able to make the argument call itself. eg
// func_name = "CreateX", tokens = 'ii', first_arg = 10, second_arg = 20
func_map[func_name](tokens,first_arg,second_arg);
I can't predict how users are going to lay out the functions and code this beforehand.
If anyone has suggestions on accomplishing this task another way, feel free to suggest. I need the user to be able to "bind" a function to the library, and for the library to call it later after it has received data from a networked client, a callback in essence.
Here is a C++11 solution. It does not support varargs functions like printall or printf, this is impossible with this technique and IMO impossible at all, or at the very least extremely tricky. Such function are difficult to use safely in an environment like yours anyway, since any bad request from any client could crash the server, with absolutely no recourse whatsoever. You probably should move to container-based interface for better safety and stability.
On the other hand, this method supports all (?) other functions uniformly.
#include <vector>
#include <iostream>
#include <functional>
#include <stdexcept>
#include <string>
#include <boost/any.hpp>
template <typename Ret, typename... Args>
Ret callfunc (std::function<Ret(Args...)> func, std::vector<boost::any> anyargs);
template <typename Ret>
Ret callfunc (std::function<Ret()> func, std::vector<boost::any> anyargs)
{
if (anyargs.size() > 0)
throw std::runtime_error("oops, argument list too long");
return func();
}
template <typename Ret, typename Arg0, typename... Args>
Ret callfunc (std::function<Ret(Arg0, Args...)> func, std::vector<boost::any> anyargs)
{
if (anyargs.size() == 0)
throw std::runtime_error("oops, argument list too short");
Arg0 arg0 = boost::any_cast<Arg0>(anyargs[0]);
anyargs.erase(anyargs.begin());
std::function<Ret(Args... args)> lambda =
([=](Args... args) -> Ret {
return func(arg0, args...);
});
return callfunc (lambda, anyargs);
}
template <typename Ret, typename... Args>
std::function<boost::any(std::vector<boost::any>)> adaptfunc (Ret (*func)(Args...)) {
std::function<Ret(Args...)> stdfunc = func;
std::function<boost::any(std::vector<boost::any>)> result =
([=](std::vector<boost::any> anyargs) -> boost::any {
return boost::any(callfunc(stdfunc, anyargs));
});
return result;
}
Basically you call adaptfunc(your_function), where your_function is a function of any type (except varargs). In return you get an std::function object that accepts a vector of boost::any and returns a boost::any. You put this object in your func_map, or do whatever else you want with them.
Types of the arguments and their number are checked at the time of actual call.
Functions returning void are not supported out of the box, because boost::any<void> is not supported. This can be dealt with easily by wrapping the return type in a simple template and specializing for void. I've left it out for clarity.
Here's a test driver:
int func1 (int a)
{
std::cout << "func1(" << a << ") = ";
return 33;
}
int func2 (double a, std::string b)
{
std::cout << "func2(" << a << ",\"" << b << "\") = ";
return 7;
}
int func3 (std::string a, double b)
{
std::cout << "func3(" << a << ",\"" << b << "\") = ";
return 7;
}
int func4 (int a, int b)
{
std::cout << "func4(" << a << "," << b << ") = ";
return a+b;
}
int main ()
{
std::vector<std::function<boost::any(std::vector<boost::any>)>> fcs = {
adaptfunc(func1), adaptfunc(func2), adaptfunc(func3), adaptfunc(func4) };
std::vector<std::vector<boost::any>> args =
{{777}, {66.6, std::string("yeah right")}, {std::string("whatever"), 0.123}, {3, 2}};
// correct calls will succeed
for (int i = 0; i < fcs.size(); ++i)
std::cout << boost::any_cast<int>(fcs[i](args[i])) << std::endl;
// incorrect calls will throw
for (int i = 0; i < fcs.size(); ++i)
try {
std::cout << boost::any_cast<int>(fcs[i](args[fcs.size()-1-i])) << std::endl;
} catch (std::exception& e) {
std::cout << "Could not call, got exception: " << e.what() << std::endl;
}
}
As already mentioned by #TonyTheLion, you can use boost::variant or boost::any to select between types at runtime:
typedef std::function<void(const std::string&, const std::vector<boost::variant<char, int>>&)> varying_args_fn;
std::map<std::string, varying_args_fn> func_map;
The you can e.g. use a static visitor to distinguish between the types. Here is a full example, note that the tokens parameter is actually no longer necessary since boost::variant knows at runtime what type is stored in it:
#include <map>
#include <vector>
#include <string>
#include <functional>
#include <iostream>
#include <boost/variant.hpp>
#include <boost/any.hpp>
typedef std::function<void(const std::string&, const std::vector<boost::variant<char, int>>&)> varying_args_fn;
void printall(const std::string& tokens, const std::vector<boost::variant<char, int>>& args) {
for (const auto& x : args) {
struct : boost::static_visitor<> {
void operator()(int i) {
std::cout << "Int: " << i << ' ';
}
void operator()(char c) {
std::cout << "Char: " << c << ' ';
}
} visitor;
boost::apply_visitor(visitor, x);
}
}
int main() {
std::map<std::string, varying_args_fn> func_map;
func_map["printall"] = printall;
func_map["printall"]("iic", {5, 10, 'x'});
}