The following code is basically a more "naive" version of the example on variant found on CPP Reference. It defines a std::variant type (line [1]) and uses std::visit to iterate through a vector of that type. Here, I used a functor (line [2]) inside the std::visit function as an attempt for a better understanding of how std::visit works.
What puzzles me the most lies in lines [4] and [5]. It appears that either Print{}, with curly brackets, or Print(), with parentheses, can serve as the first parameter to std::visit function. The later, i.e., Print(), is an instantiation and is thus supplying an object as the first parameter, which is comprehensible. I don't quite understand why the former, Print{}, works too. Can anyone shed some light on this peculiarity?
using var_t = std::variant<int, long, double, std::string>; // [1]
class Print { // [2]
public:
void operator()(int arg) {
std::cout << "Integer is " << arg << '\n';
}
void operator()(double arg) {
std::cout << "Double precision is " << arg << '\n';
}
void operator()(long arg) {
std::cout << "Long type is " << arg << '\n';
}
void operator()(const std::string& arg) {
std::cout << "String is " << arg << '\n';
}
};
std::vector<var_t> vec = {10, 15l, 1.5, "Hello, World", 900}; // [3]
for (auto& v : vec) {
//std::visit(Print{}, v); // [4]
std::visit(Print(), v); // [5]
}
Print() is a call to constructor of class Print. Print{} is list initialization of class Print. In this case the difference is only int that list initialization actually would be aggregate initialization and would init members of Print if it had any, the constructor would not.
In both cases you pass an instance of Print.
Related
Consider the following code:
void func_0()
{
std::cout << "Zero parameter function" << std::endl;
}
void func_1(int i)
{
std::cout << "One parameter function [" << i << "]" << std::endl;
}
void func_2(int i, std::string s)
{
std::cout << "One parameter function [" << i << ", " << s << "]" << std::endl;
}
int main()
{
auto f0 = boost::bind(func_0);
auto f1 = boost::bind(func_1,10);
auto f2 = boost::bind(func_2,20,"test");
f0();
f1();
f2();
}
The above code works as intended. Is there any way I can store f0, f1, f2 in a container and execute it like this:
Container cont; // stores all the bound functions.
for(auto func : cont)
{
func();
}
Will this example work for you?
std::vector<std::function<void()>> container{f0, f1, f2};
for (auto& func : container)
{
func();
}
You can read here about std::function:
Instances of std::function can store, copy, and invoke any Callable
target ...
So the template argument for this class template (void() in our case) is merely the signature of the Callable. What bind() returned in all your calls to it is exactly a Callable of the form void().
std::bind is not guaranteed to return the same type for functions with the same final interface (final = after binding). So, no, you won't be able to store functions bound with std::bind in a container. You will have to use some sort of type-erasure technique to bring them all to the same type, like std::function. A container of std::function<void()> will be able to store your bound functions (at the expense of type-erasure-related overhead).
I don't know whether it applies to boost::bind, but I suspect it is the same as std::bind in that regard.
Sample:
#include "stdafx.h"
#include <functional>
#include <iostream>
#include <string>
std::function<void(int)> Foo()
{
int v = 1;
int r = 2;
auto l = [v, r](int i)
{
std::cout << v << " " << r << " " << i << std::endl;
};
return l;
}
int main()
{
auto func = Foo();
func(3);
return 0;
}
Why func(3) can pass 3 to i which is the formal argument of the lambda in Foo(). I can't think out. thanks.
TL;DR: You don't pass your argument 3 into a function Foo. You pass it to a method of an object func.
A bit more detailed explanation is below.
First of all, I would like to clarify what a lambda is. A lambda in C++ is nothing more than an anonymous functor class, so essentially just a syntactic sugar. A closure is an instance of a lambda type. However, quite often you can hear words "lambda" and "closure" being used interchangeably.
So within your function Foo() you create a closure object l
auto l = [v, r](int i)
{
std::cout << v << " " << r << " " << i << std::endl;
};
which would be technically equivalent to this code:
struct Functor
{
Functor(int v, int r) : v_(v), r_(r) {}
void operator ()(int i) const {
std::cout << v_ << " " << r_ << " " << i << std::endl;
}
private:
int v_;
int r_;
};
Functor l(v, r);
Now, on the next line you return an std::function object.
return l; // actually creates std::function<void(int)>(l) and returns it
So in your main function a func is just an object which stores copies of values v, r obtained during a call to Foo() and defines operator(), similar to the struct above.
Therefore, calling func(3) you actually invoke an object method on a concrete object func, and without syntactic sugar it looks like func.operator()(3).
Here's a live example to illustrate my point.
Hope that helps to resolve your confusion.
I see the C++11 documentation (http://en.cppreference.com/w/cpp/language/lambda) for lambda expressions states capture by value and reference are supported but not rvalue reference. The closest SO question I could find related to this is: How to capture a unique_ptr into a lambda expression?, but it seems like my use case doesn't require the use of std::bind.
Code
#include <iostream>
#include <memory>
class Foo
{
public:
explicit Foo(int value = 0) : mValue(value) {}
// The following items are provided just to be explicit
Foo(Foo &&other) = default;
Foo &operator=(Foo &&other) = default;
Foo(const Foo &other) = delete;
Foo &operator=(const Foo &other) = delete;
~Foo() {}
int mValue;
};
void bar(std::unique_ptr<Foo> f)
{
std::cout << "bar: " << std::dec << f->mValue << "\n";
}
int main()
{
{
std::unique_ptr<Foo> f(new Foo(22));
std::cout << "main: " << std::hex << f.get() << "\n";
// Call the bar function directly (requires using std::move)
bar(std::move(f));
std::cout << "main: " << std::hex << f.get() << "\n";
}
{
std::unique_ptr<Foo> f(new Foo(99));
std::cout << "main: " << std::hex << f.get() << "\n";
// Lamda expression captures 'f' by reference and then calls the bar function (again, requires using std::move)
auto fn = [&f](){ bar(std::move(f)); };
fn(); // Execute the closure
std::cout << "main: " << std::hex << f.get() << "\n";
}
return 0;
}
Example Output
main: 0x92e010
bar: 22
main: 0
main: 0x92e010
bar: 99
main: 0
By examining the output it appears this program is running correctly (i.e., the observed results are what I expected. However, I have the following questions.
Questions
Is using the closure equivalent to the code that calls the bar function directly?
I'm asking explicitly since the documentation (see beginning of the question) about lambda expressions didn't state anything about using std::move on captured references (i.e., I want to make sure this doesn't run afoul of undefined behavior or similar bad outcomes).
If the answer to the first question is "you can't use std::move on the captured reference", then what is the right way to do this (e.g., the std::bind solution, etc)?
Is using the closure equivalent to the code that calls the bar function directly?
Yes, they're equivalent in this code. Captured references aren't special in any way that I can think of: you have fully defined behavior, as long as f is in scope and can be moved from.
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
Is it possible to mix constructors with fixed parameters and constructor templates?
My Code:
#include <iostream>
class Test {
public:
Test(std::string, int, float) {
std::cout << "normal constructor!" << std::endl;
}
template<typename ... Tn>
Test(Tn ... args) {
std::cout << "template constructor!" << std::endl;
}
};
int main() {
Test t("Hello World!", 42, 0.07f);
return 0;
}
This gives me "template constructor!". Is there a way, that my normal constructor is called?
Sure, in the event of two equally good matches, the non-template is preferred:
Test t(std::string("Hello"), 42, 0.07f);
C++ knows two basic string types: std::string and null-terminated character arrays. Instead of fixing your problem on the caller's side (as Kerrek SB suggested), you could add another overload:
class Test {
public:
Test(std::string, int, float) {
std::cout << "normal constructor!" << std::endl;
}
Test(const char*, int, float) {
std::cout << "normal constructor 2!" << std::endl;
}
template<typename ... Tn>
Test(Tn ... args) {
std::cout << "template constructor!" << std::endl;
}
};
Live example
You could also use delegating constructors to implement one of the normal constructors in terms of the other to avoid duplicating the code, e.g.
Test(const char* c, int i, float f)
: Test(std::string(c), i, f)
{
}
Live example