This question already has answers here:
How do I print out the arguments of a function using a variadic template?
(3 answers)
Closed 2 years ago.
Is there a way to create a function or a macro in C++ that you can use like Python?
What i mean is a function like:
print(i); // i is an integer.
print(i, s); // i is an integer, s is a std::string. They are separated by a white space.
A function that takes in a number of arguments, then just prints them out regardless of the types.
Use streams:
std::cout << i << ' ' << s << '\n';
For more complex formatting consider fmt, it supports the syntax for python's str.format as well as printf style formatting (but typesafe).
If you are allowed to use C++17, you can do it using fold-expression, like this:
#include <iostream>
template<class ...Args>
void print(const Args &...args) {
auto seq_started = false;
auto print_impl = [&](auto &value) mutable {
if (seq_started) {
std::cout << " " << value;
} else {
seq_started = true;
std::cout << value;
}
};
(print_impl(args), ...);
}
int main() {
print("foo", 10, "bar", 20, "baz");
return 0;
}
I assume that the question is about general solution and that print is just an example.
The answer is: yes, with a combination of overloads and templates. First you setup functions per type:
void print_impl(const std::string& arg) {
std::cout << arg;
}
void print_impl(int arg) {
// Note: this is an example. Of course cout already
// does that for us with simple
// std::cout << arg;
print_impl(convert_to_string(arg));
}
// cout already has lots of overloads, we can take
// advantage of that if needed:
template<class TArg>
void print_impl(TArg&& arg) {
std::cout << std::forward<TArg>(arg);
}
then templates:
template<class TArg>
void print(TArg&& arg) {
print_impl(std::forward<TArg>(arg));
}
template<class TArg1, class ... TArgs>
void print(TArg1&& arg1, TArgs&& ... args) {
print_impl(std::forward<TArg1>(arg1)); // <-- print first argument
print_impl(" "); // <-- insert separator, requires const std::string& overload
print(std::forward<TArgs>(args)...); // <-- recursive call
}
In the code above you can replace calls to print_impl with calls to std::cout << operator directly, if needed. Although I would keep print_impl because it is a nice layer above std::cout in case you want to replace it in the future.
Then you can use it similar to Python:
int main()
{
print("test");
print(1, 2, "foo");
print("foo", 1, 2);
return 0;
}
Related
How would I exit a function with a return value without using return.
Is there something like this in c++ :
auto random_function() {
printf("Random string"); // Gets executed
exit_with_return_value(/* Any random value. */);
printf("Same string as before"); // Doesn't get executed
}
Because I'm aware about exit() which takes a exit code.
But is there any way I could exit with a return value.
It is just that I can't call return is parentheses like this:
( return /* random value*/ );
But I can call functions in parentheses,
(exit(0));
My use case:
template <typename ...Parameters>
class Parameter_Pack
{
private:
void* paramsAddr[sizeof...(Parameters)];
public:
Parameter_Pack(Parameters ...parameters) {
size_t count = 0;
((
parameters,
this->paramsAddr[count] = malloc(sizeof(Parameters)),
*(Parameters*)paramsAddr[count] = parameters,
count++
), ...);
}
auto operator[](size_t index) {
size_t count = 0;
try {
(((count == index ? : return *
(Parameters*)paramsAddr[index] : *
(Parameters*)paramsAddr[index]), count++), ...);
} catch (Parameters...) {
std::cout << "Error: " << std::endl;
}
}
const size_t size() const {
return sizeof...(Parameters);
}
};
The problem is I can't return in auto operator[](size_t index).
The compiler error is :
"expected primary-expression before 'return'"
This doesn't answer your question directly, but instead of reinventing the wheel why not unpack the parameter pack into an std::tuple. You can then use std::get to access the object's by index.
#include <iostream>
#include <tuple>
template<typename ...Args>
static void unpack(Args&& ...args)
{
std::tuple pack{ std::forward<Args>(args)... };
int first = std::get<0>(pack);
std::cout << first << '\n';
const std::string& second = std::get<1>(pack);
std::cout << second << '\n';
bool third = std::get<2>(pack);
std::cout << std::boolalpha << third << '\n';
}
int main()
{
unpack(42, std::string{ "Some string" }, false);
}
OK, so the only thing I could come up with that kind of does what you want is to use a std::vector in conjunction with a std::variant.
Personally I think this would be an annoying API to use but it will allow you to return multiple types from the subscript operator and doesn't require a constant expression, i.e. index can be a runtime value.
#include <iostream>
#include <variant>
#include <vector>
#include <string>
template<typename ...Args>
class Pack {
public:
using Types = std::variant<Args...>;
Pack(Args... args)
: pack_{ std::move(args)... }
{}
Types& operator[](const std::size_t index) {
return pack_.at(index);
}
std::size_t size() const noexcept {
return pack_.size();
}
private:
std::vector<Types> pack_;
};
int main() {
Pack pack{42, std::string{ "Some string" }, false};
std::cout << pack.size() << '\n';
if (int* num = std::get_if<int>(&pack[0])) {
std::cout << "My num: " << *num << '\n';
}
}
return is a statement. Statements can't be part of a larger expression, so you can't return as a subexpression of some larger expression.
throw is an expression. It can be a subexpression of a larger expression, and you can throw any object you like.
It will be inconvenient for your callers, particularly if you mix it with an ordinary return. It will also not match the expectations other programmers have for how functions work. For that reason, I suggest you don't throw when you mean return.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I have a function which takes std::string type as argument, but I'd like to pass a null pointer to it and construct an empty string. Right now, I'm using if else statements to accomplish this task, but I'd like to pretty much find modern elegant solutions for this problem.
void print(int age, std::string name, int familyMembers, std::string state) {
std::cout << name << age << familyMembers << state << "\n";
}
print(10, "sara", 5, nullptr);
print(10, nullptr, nullptr, nullptr); // Doesn't work
print(nullptr, nullptr, 12, nullptr); // Doesn't work
I need a runtime solution. The following works,
std::string fromJS(const char * cstr) { return cstr ? { cstr };
but,
print(10, fromJS(nullptr), 5, fromJS(nullptr));
can become horrible as arguments increase..
I'm looking for a solution that do this automatically at print function level
Just make an override for nullptr.
void print(std::string name) {
std::cout << name << "\n";
}
void print(std::nullptr_t) {
std::cout << "\n";
}
print(nullptr);
Update: For such a "print" function with indeterminate parameters, you should use template expansion instead:
template <typename T, typename... Ts>
void print(const T& arg, const Ts&... args) {
std::cout << arg;
print(args);
}
template <typename... Ts>
void print(std::nullptr_t, const Ts&... args) {
print(args);
}
template <typename T>
void print(const T& name) {
std::cout << name << "\n";
}
void print(std::nullptr_t) {
std::cout << "\n";
}
print(1, 1.0, "hello", nullptr, "hello"s, nullptr);
Take a look at std::optional and it's value_or and nullopt instead of nullptr, so your code became
void print(std::optional<std::string> name) {
std::cout << name.value_or("empty string passed") << "\n";
}
int main()
{
print("non empty"); // prints non empty
print(nullopt); // prints empty string passed
//NOTE: in last line I used nullopt instead of nullptr
}
This question already has answers here:
is any difference between std::forward<T> and std::forward<decltype(t)>?
(2 answers)
Closed 7 years ago.
I have something like (let's say):
template <typename Collection, typename Item>
void foo_collection(Collection&& c, Item && i) {
foo(std::forward<Collection>(c), std::forward<Item>(i));
}
I don't like the fact that std::forward<Collection>(c) is so long. I'd like to do this, instead:
template <typename Collection, typename Item>
void foo_collection(Collection&& c, Item&& i) {
foo(FWD(c), FWD(i));
}
I am thinking there must be a way to do this using decltype. I figure, given the decltype(i), if I remove all references and consts from it, I'll get Item, and then it should work:
#define FWD(v) \
std::forward< \
typename std::remove_const<\
typename std::remove_reference<\
decltype(v)>::type>::type>(v)
However, this doesn't work:
void foo(int& a) { cout << "ref" << endl; }
void foo(const int& a) { cout << "cref" << endl; }
template <typename T>
void call_foo(T&& t) { foo(FWD(t)); }
int main() {
int a = 10;
foo(10); // 1) prints cref
foo(a); // 2) prints ref
call_foo(10); // 3) prints cref
call_foo(a); // 4) prints cref
return 0;
}
Why does 4 call the cref overload, and not the ref overload?
I tried #define FWD(a) std::forward<decltype(a)>(a), and in this example it did work. However, I am guessing that it won't work in all cases. Is that the case, and if so, which cases won't it work in?
Finally, if the latter approach doesn't work, is there any way to write this macro in a way that works?
#define FWD(a) std::forward<decltype(a)>(a)
will work. So long as a is the name of a variable, decltype(a) is the type it was declared as, which is what you are supposed to pass to forward as its type parameter.
If you pass in an expression, things could get strange. I cannot think up a case where it fails, however.
Naturally this doesn't work for some more advanced uses of forward.
The approach
#define FWD(a) std::forward<decltype(a)>(a)
actually works as can seen here
void foo(int& a) { cout << "lref" << endl; }
void foo(const int& a) { cout << "cref" << endl; }
void foo(int&& a) { cout << "rref" << endl; }
template <typename T>
void call_foo(T&& t) { foo(FWD(t)); }
int main() {
int a = 10;
call_foo(10); // 3) prints rref
call_foo(a); // 4) prints lref
return 0;
}
I was wondering if there is a macro or standard way (for debugging purposes) to automatically print the value of the parameters of a function f, just like __FUNCTION__ prints/shows the function signature? For example,
void foo(int x, string y) {
cout << __FUNCTIION_ARGS__ << endl;
}
should show the values of x, and y.
If there is no such magic the standard way, is it possible to write a macro/template to do this?
--Update--
Per #jxh's comment, if print inside the function in question is impossible with macro/templates, is it possible to do it automatically on the caller-side, with something like:
call(foo,x,y);
which prints every parameter value, and behaves the same with foo(x,y) as if it is called directly in every other aspect? If a value is not printable (e.g. pointers, functions), the wrapper call can just print an opaque value such as <ptr> or <noprint>.
Thanks
P.S. I am using gcc, (and also clang in the future).
My take on it :
#include <iostream>
// Dummy parameter-pack expander
template <class T>
void expand(std::initializer_list<T>) {}
// Fun
template <class Fun, class... Args>
typename std::result_of<Fun&&(Args&&...)>::type
call(Fun&& f, Args&&... args) {
// Print all parameters
std::cout << "Params : ";
expand({(std::cout << args << ' ', 0)...});
std::cout << '\n';
// Forward the call
return std::forward<Fun>(f)(std::forward<Args>(args)...);
}
// Random test function
int myFunc(std::string const &s, double d, int i) {
std::cout << s << ' ' << d << ' ' << i << '\n';
return 57;
}
int main()
{
// Painless call
std::cout << call(myFunc, "hello", 3.14, 42) << '\n';
return 0;
}
Output :
Params : hello 3.14 42
hello 3.14 42
57
Variadic templates are fun !
There is no macro for printing the arguments, but you can print the function prototype using the __PRETTY_FUNCTION__ macro
I have a method like this
template<typename T, typename U>
map<T,U> mapMapValues(map<T,U> old, T (f)(T,U))
{
map<T,U> new;
for(auto it = old.begin(); it != old.end(); ++it)
{
new[it->first] = f(it->first,it->second);
}
return new;
}
and the idea is that you'd call it like this
BOOST_AUTO_TEST_CASE(MapMapValues_basic)
{
map<int,int> test;
test[1] = 1;
map<int,int> transformedMap = VlcFunctional::mapMapValues(test,
[&](int key, int value) -> int
{
return key + 1;
}
);
}
However I get the error: no instance of function template "VlcFunctional::mapMapValues" matches the argument list argument types are: (std::map, std::allocator>>, __lambda1)
Any idea what I'm doing wrong? Visual Studio 2008 and Intel C++ compiler 11.1
Your function is expecting a function pointer, not a lambda.
In C++, there are, in general, 3 types of "callable objects".
Function pointers.
Function objects.
Lambda functions.
If you want to be able to use all of these in your function interface, then you could use std::function:
template<typename T, typename U>
map<T,U> mapMapValues(map<T,U> old, std::function<T(T, U)> f)
{
...
}
This will allow the function to be called using any of the three types of callable objects above. However, the price for this convenience is a small amount of overhead on invokations on the function (usually a null pointer check, then a call through a function pointer). This means that the function is almost certainly not inlined (except maybe with advanced WPO/LTO).
Alternatively, you could add an additional template parameter to take an arbitrary type for the second parameter. This will be more efficient, but you lose type-safety on the function used, and could lead to more code bloat.
template<typename T, typename U, typename F>
map<T,U> mapMapValues(map<T,U> old, F f)
Your parameter type declaration T (f)(T,U) is of type 'free function taking a T and a U and returning a T'. You can't pass it a lambda, a function object, or anything except an actual function with that signature.
You could solve this by changing the type of the parameter to std::function<T(T,U)> like this:
template<typename T, typename U>
map<T,U> mapMapValues(map<T,U> old, std::function<T(T,U)>)
{
}
Alternately, you could declare the function type as a template argument like this:
template<typename T, typename U, typename Fn>
map<T,U> mapMapValues(map<T,U> old, Fn fn)
{
fn(...);
}
I would like to contribute this simple but self-explanatory example. It shows how to pass "callable things" (functions, function objects, and lambdas) to a function or to an object.
// g++ -std=c++11 thisFile.cpp
#include <iostream>
#include <thread>
using namespace std;
// -----------------------------------------------------------------
class Box {
public:
function<void(string)> theFunction;
bool funValid;
Box () : funValid (false) { }
void setFun (function<void(string)> f) {
theFunction = f;
funValid = true;
}
void callIt () {
if ( ! funValid ) return;
theFunction (" hello from Box ");
}
}; // class
// -----------------------------------------------------------------
class FunClass {
public:
string msg;
FunClass (string m) : msg (m) { }
void operator() (string s) {
cout << msg << s << endl;
}
};
// -----------------------------------------------------------------
void f (string s) {
cout << s << endl;
} // ()
// -----------------------------------------------------------------
void call_it ( void (*pf) (string) ) {
pf( "call_it: hello");
} // ()
// -----------------------------------------------------------------
void call_it1 ( function<void(string)> pf ) {
pf( "call_it1: hello");
} // ()
// -----------------------------------------------------------------
int main() {
int a = 1234;
FunClass fc ( " christmas ");
f("hello");
call_it ( f );
call_it1 ( f );
// conversion ERROR: call_it ( [&] (string s) -> void { cout << s << a << endl; } );
call_it1 ( [&] (string s) -> void { cout << s << a << endl; } );
Box ca;
ca.callIt ();
ca.setFun (f);
ca.callIt ();
ca.setFun ( [&] (string s) -> void { cout << s << a << endl; } );
ca.callIt ();
ca.setFun (fc);
ca.callIt ();
} // ()
Lambda expressions with empty capture list should decay to function pointers, according to n3052. However it seems that this feature is not implemented in VC++ and only partially in g++, see my SO question.
Here is some example of how to pass a function as parameter
class YourClass
{
void YourClass::callback(void(*fptr)(int p1, int p2))
{
if(fptr != NULL)
fptr(p1, p2);
}
};
void dummyfunction(int p1, int p2)
{
cout << "inside dummyfunction " << endl;
}
YourClass yc;
// using a dummyfunction as callback
yc.callback(&dummyfunction);
// using a lambda as callback
yc.callback( [&](int p1, int p2) { cout << "inside lambda callback function" << endl; } );
// using a static member function
yc.callback( &aClass::memberfunction );