I am trying variadic template pack inside lambda function with vector.
Learning the c++ programming langage book, it's said "If you need to capture a variadic template argument, use ..." (with a simple example).
I am not able to compile it, my aim is just to be able to print the variadic type inside my lambda:
#include <iostream>
#include <vector>
#include <typeinfo>
using namespace std;
template<typename... vectType>
void printAllElements(vector<vectType...>& nbList, ostream& output, int nbToTest){
for_each(begin(nbList),end(nbList),
[&vectType...](vectType... x){
vectType... v;
output << x << endl;
output << typeid(v).name() << endl;
}
);
}
int main() {
vector<int> myVect {10,20,156,236};
printAllElements(myVect,cout, 4);
}
StackTrace:
learnC++/main.cpp:10:7: error: 'vectType' in capture list does not name a variable
[&vectType...](vectType... x){
^
learnC++/main.cpp:11:15: error: only function and template parameters can be parameter packs
vectType... v;
^
learnC++/main.cpp:12:7: error: variable 'output' cannot be implicitly captured in a lambda with no capture-default specified
output << x << endl;
Regards
Update 1:
Ok so I update this question to add the two code of Stroustrup I concataned with his advices.
Lambda & Vector
Void print_modulo(const vector<int>& v, ostream& os, int m){
for_each(begin(b),end(v),
[&os,m](int x){ if (x%m==0 os << w << '\n');}
}
The version using lambda is a clear winner. But if you really want a
name, you can just provide one ..
Capture template
If you need to capture template argument, use ... For example:
template<typename... Var>
void algo(int s, Var... v){
auto helper = [&s,&v...]{return s*(h1(v...)+h2(v...);)};
}
h1 & h2 are simple examples functions
I will try to explain what is wrong in your code, but to be truly understood, you need to read some good books.
std::vector is a homogeneous container, all its elements have only one same type. This vector<vectType...> is pointless. For example, std::vector<int> has all int elements; there is no such a thing std::vector<int, double, short>. Thus if you want to print the typeid for some different types, your approach is wrong from the beginning.
In your own code [&vectType...], those vectType are types, that's also pointless. In your quoted code [&s,&v...], those v are variables, thus correct.
Such vectType... v; declaration is invented by yourself, it's not C++.
The following is a simple example in C++14 if you want to print variables' typeid in a generic way:
#include <iostream>
template<class... Args>
void print_all_typeid(Args const &...args)
{
auto dumb = [] (auto... x) {};
auto printer = [] (auto const &x) {
std::cout << typeid(x).name() << "\n";
return true;
};
dumb(printer(args)...);
}
int main() {
print_all_typeid(std::cin, 12, std::cout, 1L, 2.0, 3.f);
}
Related
I want to explore how I can use std::any instead of void * or such constructs for message passing. So I created an example code to test this - see below.
The use of std::any looks nice, but I want to switch through the types to check which type the std::any is. It might no be possible, and I know I can use a if/elseif... block instead, but it would be very nice if I can create a switch statement so that if I use this in real code with 10-20 different types it will be more readable.
#include <string>
#include <iostream>
#include <sstream>
#include <any>
#include <typeindex>
struct ints { int a{1}; int b{2}; };
struct strings { std::string a{"string1"}; std::string b{"string2"}; };
void send_msg(std::any item)
{
switch (item.type().hash_code()) // <------- HERE
{
case typeid(ints).hash_code(): // <------- HERE
std::cout << "ints" << std::endl;
break;
case typeid(strings).hash_code():
std::cout << "strings" << std::endl;
break;
default:
std::cout << "unknown type\n";
}
}
int main()
{
strings s;
send_msg(s);
ints i;
send_msg(i);
}
live example: https://godbolt.org/z/xPrMYM
I can't switch on the type_info returned by std::any::type, but I can switch on the hash_code() of the type_info, but that is not a constexpr I hoped it was though!
so I also tried getting the address of the type info and a few other tricks that I could find. But no luck so far...
Is there such a way?
I would also suggest a variant here if possible but for the concrete question:
If you can use boost and C++17 is your referred standard: They provide an extended typeid handling that can also be used for several compile time checks, see
https://www.boost.org/doc/libs/1_67_0/boost/type_index/ctti_type_index.hpp
Its underlying rawType is a const char* constexpr and the typeIndex itself can be used as a perfect replacement for std::type_info. Since the standard guarantees unique addresses for these type identifiers, even a simple address comparison should be possible here (not sure why this simplification is currently out commented inside the boost headers though).
To be usable with any, you might have to wrap it or to use a simple own any type.
What you're asking is std::visit, but with std::any
template<typename... Ts, typename F>
bool visit(F&& f, std::any x)
{
auto result = ((x.type() == typeid(Ts) ?
(std::forward<F>(f)(*std::any_cast<Ts>(&x)), true) : false) || ...);
return result;
}
Since the std::any might contain anything, the visit might fail at runtime, which is why you certainly need some way to report the error†.
Use as
bool send_msg(std::any x)
{
auto f = [](auto&& x){
std::cout << x << '\n';
};
return visit<std::string, int>(f, x);
}
But then, using std::variant is just simpler
void send_msg(std::variant<std::string, int> x)
{
auto f = [](auto&& x){
std::cout << x << '\n';
};
visit(f, x);
}
†The complete visit implementation would be a bit more complicated.
In Python, it is possible to store a function pointer with different number of arguments and store the arguments in a list and then unpack the list and call that function like:
def Func(x1, x2):
return x1+x2
ArgList = [1.2, 3.22]
MyClass.Store(Func)
MyClass.FuncPtr(*ArgList)
Is it possible in c++ to do a similar thing?
For example, store the function with the variable-number of inputs and the values in a std::vector and call function pointer by that vector?
I don’t want to define the argument list as a vector.
Is it possible in c++ to do a similar thing?
If you know the arguments(types) at compile-time, of-course you can!
For, instance like/similar to what #Evg suggested, make the Func as a variadic-generic-lambda, and with the support of c++17's std::apply,(for future readers) you could do.
(See a demo)
#include <iostream>
#include <utility> // std::forward
#include <tuple> // std::apply
constexpr auto func_lambda = [](auto&&... args) {
return (std::forward<decltype(args)>(args) + ...); // fold expression
};
int main()
{
std::cout << std::apply(func_lambda, std::make_tuple(1, 2, 3)); // prints 6!
return 0;
}
And now as per your python demo code, you could pack the above idea into to a class-template.
Here, you can avoid the use of std::function, as the Func will be the lambda you pass, and can be stored as compiler deduced lambda unspecified type.
(See Demo Online)
#include <iostream>
#include <utility> // std::forward
#include <tuple> //std::apply, std::make_tuple
// `Func` as variadic-generic-lambda
constexpr auto func_lambda = [](auto&&... args) noexcept {
return (std::forward<decltype(args)>(args) + ...);
};
template<typename Func>
class MyClass final
{
Func mFunction;
public:
explicit MyClass(Func func) // Store: pass the lambda here!
: mFunction{ func }
{}
template<typename... Args> // to execute the `Func` with `Args`!
constexpr auto execute(Args&&... args) const noexcept
{
return std::apply(mFunction, std::make_tuple(std::forward<Args>(args)...));
}
};
int main()
{
MyClass myClass{ func_lambda }; // MyClass.Store(Func)
std::cout << myClass.execute(1.2, 2.82, 3); // MyClass.FuncPtr(*ArgList)
return 0;
}
Output:
7.02
Unfortunately it is not possible to call an arbitrary function passing arbitrary values in a complete dynamic way at runtime. At least some part of the C++ code must compile a static call to a function with the same exact signature.
The problem is that in C++ the parameter passing can only be handled by the compiler and even variadic functions (e.g. printf) where only inspection is performed at runtime normally require a different and simpler calling convention.
One technical problem is that modern ABIs are extremely complex and asymmetrical (e.g. some parameters in registers, some in special FPU registers, some in the stack) and are only handled at compile time.
What you can do is "wrap" the functions you want to be able to call in a function accepting for example an std::vector of generic values and then calling the function passing those parameters converted to the proper type, e.g. something like
Value myabs(const std::vector<Value>& args) {
if (args.size() != 1) throw std::runtime_error("Bad arity");
return Value(fabs(args[0].to<double>()));
}
then it is easy to dynamically call these wrappers because the signature is the same for all of them.
Those wrappers unfortunately must be written (or generated) for each of the functions you need to be able to call so the compiler can actually generate the code needed to call the regular C++ functions.
I am not a template expert, but C++ metaprogramming can be used to generate the wrappers instead of coding each of them manually or writing an external code generator.
This is a very basic example:
typedef Value (*FWrapper)(const std::vector<Value>&);
template<typename RV, typename T1, typename T2, RV (*f)(T1, T2)>
Value wrapper2(const std::vector<Value>& args) {
if (args.size() != 2) throw std::runtime_error("Bad arity");
return f(args[0].to<T1>(), args[1].to<T2>());
}
For example to wrap double atan2(double, double) you can simply write:
FWrapper myatan2 = &wrapper2<double, double, double, &atan2>;
I tried a bit without success to avoid passing explicitly the return value type and number and types of parameters and to extract them instead from the passed function pointer, but may be that is also possible or even practical with recent C++.
The idea is basically to invoke the compiler to build a specific function call on demand when doing a template instantiation.
Not exactly the same thing but in C++ you can apply a combining function to a range of values to produce a single result. std::accumulate can help you here. However, it works with a given range, not variadic arguments.
#include <numeric>
#include <vector>
#include <functional>
#include <iostream>
class MyClass
{
public:
template<typename F, typename T>
T Execute(F &&fn, const T initialValue, const std::vector<T> &values)
{
auto result = std::accumulate(values.begin(), values.end(),
initialValue, std::forward<F>(fn));
return result;
}
};
int main()
{
MyClass cls;
std::vector<double> values = { 1.2, 3.22 };
auto sum = cls.Execute(std::plus<double>{}, 0.0, values);
std::cout << "Sum = " << sum << std::endl;
auto product = cls.Execute(std::multiplies<double>{}, 1.0, values);
std::cout << "Product = " << product << std::endl;
std::vector<int> values2 = { 10, 20 };
auto subtractFrom200 = cls.Execute(std::minus<int>{}, 200, values2);
std::cout << "Subtract from 200 = " << subtractFrom200 << std::endl;
std::vector<std::string> mystrings = {"Hello", " ", " world", ". ", "Bye!"};
auto concatenate = cls.Execute([](std::string a, std::string b){ return a + b ;}, std::string(), mystrings);
std::cout << "Concatenation = " << concatenate << std::endl;
std::vector<double> values3 = {100, 98, 3.5, 50};
auto findMin = [](double a, double b){ return std::min(a, b); };
auto lowest = cls.Execute(findMin, values3.front(), values3);
std::cout << "Min = " << lowest << std::endl;
}
Demo
Note: the fourth parameter to std::accumulate is optional and if omitted it will return the sum of the values. However, you can provide your own binary function if you want to do something else, e.g. multiplication or subtraction.
I am learning functional programming in C++. My intention is to pass a non generic function as argument. I know about the template method, however I would like to restrict the function signature as part of the API design. I worked out 4 different methods example on cpp.sh:
// Example program
#include <iostream>
#include <string>
#include <functional>
typedef int(functor_type)(int);
int by_forwarding(functor_type &&x) {
return x(1);
}
int functor_by_value(functor_type x) {
return x(1);
}
int std_func_by_value(std::function<functor_type> x) {
return x(1);
}
int std_func_by_forwarding(std::function<functor_type> &&x) {
return x(1);
}
int main()
{
std::cout << functor_by_value([](int a){return a;}); // works
std::cout << std_func_by_value([](int a){return a;}); // works
std::cout << std_func_by_forwarding(std::move([](int a){return a;})); // works
//std::cout << by_forwarding([](int a){return a;}); // how to move lambda with forwarding ?
}
Is any of the above attempts correct? If not, how do i achieve my goal?
(based on clarification from comments)
Signature can be restricted by using std::is_invocable:
template<typename x_Action> auto
functor_by_value(x_Action && action)
{
static_assert(std::is_invocable_r_v<int, x_Action, int>);
return action(1);
}
online compiler
Other alternative:
template <typename Func>
auto functor_by_value(Func&& f)
-> decltype(std::forward<Func>(f)(1))
{
return std::forward<Func>(f)(1);
}
however I would like to restrict the function signature as part of the API design.
So restrict it:
#include <functional>
#include <type_traits>
#include <iostream>
/// #tparam F is a type which is callable, accepting an int and returning an int
template
<
class F,
std::enable_if_t
<
std::is_convertible_v<F, std::function<int(int)>>
>* = nullptr
>
int myfunc(F &&x) {
return x(1);
}
int main()
{
auto a = myfunc([](int x) { std::cout << x << std::endl; return 1; });
// does not compile
// auto b = myfunc([]() { std::cout << "foo" << std::endl; return 1; });
}
As usual, this depends on how good your compiler is today, and how good it will be in the future.
Currently, compilers are not very good at optimizing std::function. Surprisingly, std::function is a complicated object that sometimes has to allocate memory to maintain stateful lambda functions. It also complicates matters that std::function has to be able to refer to member function, regular functions, and lambdas, and do it in a transparent manner. This transparency has a hefty runtime cost.
So, if you want the fastest possible code, you should be careful with std::function. For that reason the first variant is the fastest (on today's compilers):
int functor_by_value(functor_type x) {
return x(1);
}
It simply passes a pointer to a function.
When stateful lambdas are involved you have only two options. Either pass the lambda as a template argument, or convert to std::function. Hence, if you want the fastest code possible with lambdas (in today's compilers), you'd pass the function as a templated argument.
Since a lambda function may have a big state, passing it around may copy the big state (when copy elision is not possible). GCC will construct the lambda directly on the parameter list (with no copy), but a nested function will invoke a copy constructor for the lambda. To avoid that, either pass it by const reference (in that case it can't be mutable), or by rvalue reference:
template<class Func>
void run2(const Func & f)
{
std::cout << "Running\n";
f();
}
template<class Func>
void run(const Func & f)
{
run2(f);
}
int main()
{
run([s=BigState()]() { std::cout << "apply\n"; });
return 0;
}
Or:
template<class Func>
void run2(Func && f)
{
f();
}
template<class Func>
void run(Func && f)
{
run2(std::forward<Func>(f));
}
int main()
{
run([s=BigState()]() { std::cout << "apply\n"; });
return 0;
}
Without using references, the BigState() will be copied when the lambda is copied.
UPDATE:
After reading the question again I see that it wants to restrict the signature
template<typename Func,
typename = std::enable_if_t<
std::is_convertible_v<decltype(Func(1)), int>>>
void run2(const Func & f)
{
std::cout << "Running\n";
f();
}
This will restrict it to any function that can accept int (possibly with an implicit cast), and returns an int or any type that is implicitly cast to int. However, if you want to accept only function-like objects that accept exactly int and return exactly int you can see if the lambda is convertible to std::function<int(int)>
I'm writing a simple test to see how C++11 Lambdas can be used for the purpose of maximizing code reuse. I have a function, fill_vector() and in one case I'd like it to simply fill a vector with random numbers, but in another case I'd like it to also provide me with the maximum of those numbers.
Here's what I have so far:
#include <iostream>
#include <random>
#include <vector>
#include <algorithm>
#include <iterator>
template <class Function>
void fill_vector(std::vector<int> &v, Function side)
{
for(auto i=v.begin(); i!=v.end(); ++i)
{
*i = rand() % 100;
}
side.lambda(v);
}
class null_test
{
public:
constexpr static auto lambda = [] (std::vector<int> x) { };
};
class test
{
public:
test() : max(0) { }
int max;
static auto lambda = [=] (std::vector<int> x) { max =
std::max_element(x.begin(),x.end()); };
};
int main()
{
std::vector<int> v(20);
null_test n;
fill_vector(v,n);
std::copy(v.begin(),v.end(),std::ostream_iterator<int>(std::cout," "));
std::cout << std::endl;
std::vector<int> v2(20);
test t;
fill_vector(v2,t);
std::copy(v.begin(),v.end(),std::ostream_iterator<int>(std::cout," "));
std::cout << std::endl;
std::cout << t.max << std::endl;
return 0;
}
Which results in the error: ‘this’ was not captured for this lambda function, pointing at my lambda defined in test. I've tried all sorts of capture statements and can't seem to get anything to work. What am I missing?
Also, is it possible to use a lambda inside the loop of fill_vector that could, say, extract every nth element filled? My goal here is to be able to reuse a function like fill_vector as much as possible for other functions that might need slight variations of it in a bigger project.
Looking at your class test:
class test
{
public:
int max;
static auto lambda = [=] (std::vector<int> x) {
max = std::max_element(x.begin(),x.end());
};
};
There are several problems here:
operator() on a lambda is const, and you are trying to modify a member.
You are trying to assign the value to an external variable, but are capturing it by-value, so even if you made the lambda mutable, nothing would happen.
You are trying to assign a member of a class using a static function that does not take an instance of that class.
As dyp points out, std::max_element returns an iterator, not the actual element.
The lambda you want to write probably looks like this:
test t;
std::vector<int> v2(20);
fill_vector(v2, [&t](const std::vector<int>& x){
t.max = *std::max_element(x.begin(), x.end());
});
Just change your fill_vector() function to take a callable, rather than something that has a callable.
I know this question might be a little weird but the creators of C++ made it so that whenever we create a function in C++ we can specify what we want our parameters to be for example we can create a function like this:
void function(int test);
As well as we can create a function like this:
void function(std::string test);
How do I re-create that effect? I'm in the midst of creating a delegate class that works somewhat like CA# delegates but I'm having a problem when it comes to the parameters. I don't know what type of variable they'll want to store in the delegate so I have to implement something that they can specify which variable types they'll be using. Something like this:
Delegate myDelegate(std::string, int, float);
Is it possible to do that? I've looked into variadic functions but you have to know which type to cast it too. I know I could have indicators like "%d and %s" just like the printf function but is there a way to implement it so that it accepts the object names rather than a indicator? I hope this is simple to understand.
You can use variadic argument lists. Here is a quick example:
#include <algorithm>
#include <iostream>
#include <vector>
#include <functional>
template <typename... T>
class Delegate {
std::vector<std::function<void(T...)>> d_delegates;
public:
template <typename F>
void add(F&& f) { this->d_delegates.push_back(std::forward<F>(f)); }
template <typename... S>
void operator()(S... args) const {
std::for_each(this->d_delegates.begin(), this->d_delegates.end(),
[&](std::function<void(T...)> const& f){ f(args...); });
}
};
void f1(int i) { std::cout << "f1(" << i << ")\n"; }
void f2(int i, double d) { std::cout << "f2(" << i << ", " << d << ")\n"; }
int main() {
Delegate<int> d1;
d1.add(f1);
d1(17);
Delegate<int, double> d2;
d2.add(f2);
d2(42, 3.14);
}
A simple solution would just be function overloading. Also, if future code maintenance is required, it would provide the most clarity (at least that is my hunch). Anyway, this would produce exactly the behavior you are describing.