I try to extract all single blocks from a block matrix. However the BlockMatrixClass from the library I am using only allows access through the following indices:
Dune::index_constant<0>(), Dune::index_constant<1>(),...
They resolve to std::integral_constant<long unsigned int, 0>().
How I can alter the following code to be valid? Without changing the library.
for(std::size_t i=0; i<3; i++){
for(std::size_t j=0; j<3; j++){
const auto& m = jacobian[Dune::index_constant<i>()][Dune::index_constant<j>()];
}
}
At the moment I get the error
error: the value of ‘j’ is not usable in a constant expression
401 | t auto& m = jacobian[Dune::index_constant<i>()][Dune::index_constant<j>()];
Iterating over a compile time sequence is not a completely solved problem since they all rely on various workaround and there is many ways to do it.
My preferred way is to use an index sequence, and unroll it using fold expressions:
Simply define this:
template<typename T, T... S, typename F>
constexpr void for_sequence(std::integer_sequence<T, S...>, F&& f) {
(static_cast<void>(f(std::integral_constant<T, S>{})), ...);
}
Then, use it like that:
for_sequence(std::make_index_sequence<3>{}, [&](auto i) {
for_sequence(std::make_index_sequence<3>{}, [&](auto j) {
const auto& m = jacobian[Dune::index_constant<i>()][Dune::index_constant<j>()];
});
});
The variable i and j here are integral constants and can be used in template parameters. The actual std::integer_sequence you send to the function dictate with what value to instantiate the innermost lambda.
If jacobian can use those integral constant directly instead of their own Dune::index_constant, you can simply write this:
for_sequence(std::make_index_sequence<3>{}, [&](auto i) {
for_sequence(std::make_index_sequence<3>{}, [&](auto j) {
const auto& m = jacobian[i][j];
});
});
#include <cstdint>
#include <cstddef>
#include <utility>
template <size_t index, size_t end>
void for_loop () {
if constexpr (index == end) {
return;
}
constexpr size_t i = index / 3;
constexpr size_t j = index % 3;
const auto& m = jacobian[Dune::index_constant<i>()][Dune::index_constant<j>()];
impl<index + 1, end>();
}
template <size_t end>
void for_loop_to() {
for_loop<0, end>();
}
int main ()
{
for_loop_to<9>();
}
Would something like this work for a constexpr for loop type thing? This works for C++17 (since it requires the constexpr if) but more verbose versions would be implemented for earlier c++ versions. Also I didn't plumb jacobian through to the inner function, but you could do that with a struct wrapper.
You can unroll the loops:
const auto& m = jacobian[Dune::index_constant<0>()][Dune::index_constant<0>()];
const auto& m = jacobian[Dune::index_constant<0>()][Dune::index_constant<1>()];
const auto& m = jacobian[Dune::index_constant<0>()][Dune::index_constant<2>()];
const auto& m = jacobian[Dune::index_constant<1>()][Dune::index_constant<0>()];
const auto& m = jacobian[Dune::index_constant<1>()][Dune::index_constant<1>()];
const auto& m = jacobian[Dune::index_constant<1>()][Dune::index_constant<2>()];
const auto& m = jacobian[Dune::index_constant<2>()][Dune::index_constant<0>()];
const auto& m = jacobian[Dune::index_constant<2>()][Dune::index_constant<1>()];
const auto& m = jacobian[Dune::index_constant<2>()][Dune::index_constant<2>()];
If thats not an option you can apply some form of compile time for:
#include <utility>
#include <iostream>
template <template<size_t> class F,size_t ... I>
void for_impl(std::index_sequence<I...>){
(F<I>{}(),...);
}
template <template<size_t> class F,std::size_t N,typename Indices = std::make_index_sequence<N>>
void for_(){
for_impl<F>(Indices{});
}
template <size_t i>
struct foo{
void operator()() {
std::cout << i << "\n";
}
};
int main() {
for_<foo,5>();
}
Here only outlined for one loop. I wasn't sure if you need both loops unrolled at compile time. In the example foo is the template you would wrap the loop body inside.
Lets say that you have a function which generates some security token for your application, such as some hash salt, or maybe a symetric or asymetric key.
Now lets say that you have this function in your C++ as a constexpr and that you generate keys for your build based on some information (like, the build number, a timestamp, something else).
You being a diligent programmer make sure and call this in the appropriate ways to ensure it's only called at compile time, and thus the dead stripper removes the code from the final executable.
However, you can't ever be sure that someone else isn't going to call it in an unsafe way, or that maybe the compiler won't strip the function out, and then your security token algorithm will become public knowledge, making it more easy for would be attackers to guess future tokens.
Or, security aside, let's say the function takes a long time to execute and you want to make sure it never happens during runtime and causes a bad user experience for your end users.
Are there any ways to ensure that a constexpr function can never be called at runtime? Or alternately, throwing an assert or similar at runtime would be ok, but not as ideal obviously as a compile error would be.
I've heard that there is some way involving throwing an exception type that doesn't exist, so that if the constexpr function is not deadstripped out, you'll get a linker error, but have heard that this only works on some compilers.
Distantly related question: Force constexpr to be evaluated at compile time
In C++20 you can just replace constexpr by consteval to enforce a function to be always evaluated at compile time.
Example:
int rt_function(int v){ return v; }
constexpr int rt_ct_function(int v){ return v; }
consteval int ct_function(int v){ return v; }
int main(){
constexpr int ct_value = 1; // compile value
int rt_value = 2; // runtime value
int a = rt_function(ct_value);
int b = rt_ct_function(ct_value);
int c = ct_function(ct_value);
int d = rt_function(rt_value);
int e = rt_ct_function(rt_value);
int f = ct_function(rt_value); // ERROR: runtime value
constexpr int g = rt_function(ct_value); // ERROR: runtime function
constexpr int h = rt_ct_function(ct_value);
constexpr int i = ct_function(ct_value);
}
Pre C++20 workaround
You can enforce the use of it in a constant expression:
#include<utility>
template<typename T, T V>
constexpr auto ct() { return V; }
template<typename T>
constexpr auto func() {
return ct<decltype(std::declval<T>().value()), T{}.value()>();
}
template<typename T>
struct S {
constexpr S() {}
constexpr T value() { return T{}; }
};
template<typename T>
struct U {
U() {}
T value() { return T{}; }
};
int main() {
func<S<int>>();
// won't work
//func<U<int>>();
}
By using the result of the function as a template argument, you got an error if it can't be solved at compile-time.
A theoretical solution (as templates should be Turing complete) - don't use constexpr functions and fall back onto the good-old std=c++0x style of computing using exclusively struct template with values. For example, don't do
constexpr uintmax_t fact(uint n) {
return n>1 ? n*fact(n-1) : (n==1 ? 1 : 0);
}
but
template <uint N> struct fact {
uintmax_t value=N*fact<N-1>::value;
}
template <> struct fact<1>
uintmax_t value=1;
}
template <> struct fact<0>
uintmax_t value=0;
}
The struct approach is guaranteed to be evaluated exclusively at compile time.
The fact the guys at boost managed to do a compile time parser is a strong signal that, albeit tedious, this approach should be feasible - it's a one-off cost, maybe one can consider it an investment.
For example:
to power struct:
// ***Warning: note the unusual order of (power, base) for the parameters
// *** due to the default val for the base
template <unsigned long exponent, std::uintmax_t base=10>
struct pow_struct
{
private:
static constexpr uintmax_t at_half_pow=pow_struct<exponent / 2, base>::value;
public:
static constexpr uintmax_t value=
at_half_pow*at_half_pow*(exponent % 2 ? base : 1)
;
};
// not necessary, but will cut the recursion one step
template <std::uintmax_t base>
struct pow_struct<1, base>
{
static constexpr uintmax_t value=base;
};
template <std::uintmax_t base>
struct pow_struct<0,base>
{
static constexpr uintmax_t value=1;
};
The build token
template <uint vmajor, uint vminor, uint build>
struct build_token {
constexpr uintmax_t value=
vmajor*pow_struct<9>::value
+ vminor*pow_struct<6>::value
+ build_number
;
}
In the upcoming C++20 there will be consteval specifier.
consteval - specifies that a function is an immediate function, that is, every call to the function must produce a compile-time constant
Since now we have C++17, there is an easier solution:
template <auto V>
struct constant {
constexpr static decltype(V) value = V;
};
The key is that non-type arguments can be declared as auto. If you are using standards before C++17 you may have to use std::integral_constant. There is also a proposal about the constant helper class.
An example:
template <auto V>
struct constant {
constexpr static decltype(V) value = V;
};
constexpr uint64_t factorial(int n) {
if (n <= 0) {
return 1;
}
return n * factorial(n - 1);
}
int main() {
std::cout << "20! = " << constant<factorial(20)>::value << std::endl;
return 0;
}
Have your function take template parameters instead of arguments and implement your logic in a lambda.
#include <iostream>
template< uint64_t N >
constexpr uint64_t factorial() {
// note that we need to pass the lambda to itself to make the recursive call
auto f = []( uint64_t n, auto& f ) -> uint64_t {
if ( n < 2 ) return 1;
return n * f( n - 1, f );
};
return f( N, f );
}
using namespace std;
int main() {
cout << factorial<5>() << std::endl;
}
Lets say that you have a function which generates some security token for your application, such as some hash salt, or maybe a symetric or asymetric key.
Now lets say that you have this function in your C++ as a constexpr and that you generate keys for your build based on some information (like, the build number, a timestamp, something else).
You being a diligent programmer make sure and call this in the appropriate ways to ensure it's only called at compile time, and thus the dead stripper removes the code from the final executable.
However, you can't ever be sure that someone else isn't going to call it in an unsafe way, or that maybe the compiler won't strip the function out, and then your security token algorithm will become public knowledge, making it more easy for would be attackers to guess future tokens.
Or, security aside, let's say the function takes a long time to execute and you want to make sure it never happens during runtime and causes a bad user experience for your end users.
Are there any ways to ensure that a constexpr function can never be called at runtime? Or alternately, throwing an assert or similar at runtime would be ok, but not as ideal obviously as a compile error would be.
I've heard that there is some way involving throwing an exception type that doesn't exist, so that if the constexpr function is not deadstripped out, you'll get a linker error, but have heard that this only works on some compilers.
Distantly related question: Force constexpr to be evaluated at compile time
In C++20 you can just replace constexpr by consteval to enforce a function to be always evaluated at compile time.
Example:
int rt_function(int v){ return v; }
constexpr int rt_ct_function(int v){ return v; }
consteval int ct_function(int v){ return v; }
int main(){
constexpr int ct_value = 1; // compile value
int rt_value = 2; // runtime value
int a = rt_function(ct_value);
int b = rt_ct_function(ct_value);
int c = ct_function(ct_value);
int d = rt_function(rt_value);
int e = rt_ct_function(rt_value);
int f = ct_function(rt_value); // ERROR: runtime value
constexpr int g = rt_function(ct_value); // ERROR: runtime function
constexpr int h = rt_ct_function(ct_value);
constexpr int i = ct_function(ct_value);
}
Pre C++20 workaround
You can enforce the use of it in a constant expression:
#include<utility>
template<typename T, T V>
constexpr auto ct() { return V; }
template<typename T>
constexpr auto func() {
return ct<decltype(std::declval<T>().value()), T{}.value()>();
}
template<typename T>
struct S {
constexpr S() {}
constexpr T value() { return T{}; }
};
template<typename T>
struct U {
U() {}
T value() { return T{}; }
};
int main() {
func<S<int>>();
// won't work
//func<U<int>>();
}
By using the result of the function as a template argument, you got an error if it can't be solved at compile-time.
A theoretical solution (as templates should be Turing complete) - don't use constexpr functions and fall back onto the good-old std=c++0x style of computing using exclusively struct template with values. For example, don't do
constexpr uintmax_t fact(uint n) {
return n>1 ? n*fact(n-1) : (n==1 ? 1 : 0);
}
but
template <uint N> struct fact {
uintmax_t value=N*fact<N-1>::value;
}
template <> struct fact<1>
uintmax_t value=1;
}
template <> struct fact<0>
uintmax_t value=0;
}
The struct approach is guaranteed to be evaluated exclusively at compile time.
The fact the guys at boost managed to do a compile time parser is a strong signal that, albeit tedious, this approach should be feasible - it's a one-off cost, maybe one can consider it an investment.
For example:
to power struct:
// ***Warning: note the unusual order of (power, base) for the parameters
// *** due to the default val for the base
template <unsigned long exponent, std::uintmax_t base=10>
struct pow_struct
{
private:
static constexpr uintmax_t at_half_pow=pow_struct<exponent / 2, base>::value;
public:
static constexpr uintmax_t value=
at_half_pow*at_half_pow*(exponent % 2 ? base : 1)
;
};
// not necessary, but will cut the recursion one step
template <std::uintmax_t base>
struct pow_struct<1, base>
{
static constexpr uintmax_t value=base;
};
template <std::uintmax_t base>
struct pow_struct<0,base>
{
static constexpr uintmax_t value=1;
};
The build token
template <uint vmajor, uint vminor, uint build>
struct build_token {
constexpr uintmax_t value=
vmajor*pow_struct<9>::value
+ vminor*pow_struct<6>::value
+ build_number
;
}
In the upcoming C++20 there will be consteval specifier.
consteval - specifies that a function is an immediate function, that is, every call to the function must produce a compile-time constant
Since now we have C++17, there is an easier solution:
template <auto V>
struct constant {
constexpr static decltype(V) value = V;
};
The key is that non-type arguments can be declared as auto. If you are using standards before C++17 you may have to use std::integral_constant. There is also a proposal about the constant helper class.
An example:
template <auto V>
struct constant {
constexpr static decltype(V) value = V;
};
constexpr uint64_t factorial(int n) {
if (n <= 0) {
return 1;
}
return n * factorial(n - 1);
}
int main() {
std::cout << "20! = " << constant<factorial(20)>::value << std::endl;
return 0;
}
Have your function take template parameters instead of arguments and implement your logic in a lambda.
#include <iostream>
template< uint64_t N >
constexpr uint64_t factorial() {
// note that we need to pass the lambda to itself to make the recursive call
auto f = []( uint64_t n, auto& f ) -> uint64_t {
if ( n < 2 ) return 1;
return n * f( n - 1, f );
};
return f( N, f );
}
using namespace std;
int main() {
cout << factorial<5>() << std::endl;
}
Here is an example case of what I'm trying to do (it is a "test" case just to illustrate the problem) :
#include <iostream>
#include <type_traits>
#include <ratio>
template<int Int, typename Type>
constexpr Type f(const Type x)
{
return Int*x;
}
template<class Ratio, typename Type,
class = typename std::enable_if<Ratio::den != 0>::type>
constexpr Type f(const Type x)
{
return (x*Ratio::num)/Ratio::den;
}
template</*An int OR a type*/ Something, typename Type>
constexpr Type g(const Type x)
{
return f<Something, Type>(x);
}
int main()
{
std::cout<<f<1>(42.)<<std::endl;
std::cout<<f<std::kilo>(42.)<<std::endl;
}
As you can see, there are two versions of the f() function : the first one takes an int as a template parameter, and the second one takes a std::ratio. The problem is the following :
I would like to "wrap" this function through g() which can take an int OR a std::ratio as first template parameter and call the good version of f().
How to do that without writing two g() functions ? In other words, what do I have to write instead of /*An int OR a type*/ ?
Here's how I would do it, but I've changed your interface slightly:
#include <iostream>
#include <type_traits>
#include <ratio>
template <typename Type>
constexpr
Type
f(int Int, Type x)
{
return Int*x;
}
template <std::intmax_t N, std::intmax_t D, typename Type>
constexpr
Type
f(std::ratio<N, D> r, Type x)
{
// Note use of r.num and r.den instead of N and D leads to
// less probability of overflow. For example if N == 8
// and D == 12, then r.num == 2 and r.den == 3 because
// ratio reduces the fraction to lowest terms.
return x*r.num/r.den;
}
template <class T, class U>
constexpr
typename std::remove_reference<U>::type
g(T&& t, U&& u)
{
return f(static_cast<T&&>(t), static_cast<U&&>(u));
}
int main()
{
constexpr auto h = g(1, 42.);
constexpr auto i = g(std::kilo(), 42.);
std::cout<< h << std::endl;
std::cout<< i << std::endl;
}
42
42000
Notes:
I've taken advantage of constexpr to not pass compile-time constants via template parameters (that's what constexpr is for).
g is now just a perfect forwarder. However I was unable to use std::forward because it isn't marked up with constexpr (arguably a defect in C++11). So I dropped down to use static_cast<T&&> instead. Perfect forwarding is a little bit overkill here. But it is a good idiom to be thoroughly familiar with.
How to do that without writing two g() functions ?
You don't. There is no way in C++ to take either a type or a value of some type, except through overloading.
It is not possible to have a template parameter taking both type and non-type values.
Solution 1:
Overloaded functions.
Solution 2:
You can store values in types. Ex:
template<int n>
struct store_int
{
static const int num = n;
static const int den = 1;
};
template<class Ratio, typename Type,
class = typename std::enable_if<Ratio::den != 0>::type>
constexpr Type f(const Type x)
{
return (x*Ratio::num)/Ratio::den;
}
template<typename Something, typename Type>
constexpr Type g(const Type x)
{
return f<Something, Type>(x);
}
But with this solution you will have to specify g<store_int<42> >(...) instead of g<42>(...)
If the function is small, I advise you to use overloading.
I am new to C++11. I am writing the following recursive lambda function, but it doesn't compile.
sum.cpp
#include <iostream>
#include <functional>
auto term = [](int a)->int {
return a*a;
};
auto next = [](int a)->int {
return ++a;
};
auto sum = [term,next,&sum](int a, int b)mutable ->int {
if(a>b)
return 0;
else
return term(a) + sum(next(a),b);
};
int main(){
std::cout<<sum(1,10)<<std::endl;
return 0;
}
compilation error:
vimal#linux-718q:~/Study/09C++/c++0x/lambda> g++ -std=c++0x sum.cpp
sum.cpp: In lambda function:
sum.cpp:18:36: error: ‘((<lambda(int, int)>*)this)-><lambda(int, int)>::sum’ cannot be used as a function
gcc version
gcc version 4.5.0 20091231 (experimental) (GCC)
But if I change the declaration of sum() as below, it works:
std::function<int(int,int)> sum = [term,next,&sum](int a, int b)->int {
if(a>b)
return 0;
else
return term(a) + sum(next(a),b);
};
Could someone please throw light on this?
Think about the difference between the auto version and the fully specified type version. The auto keyword infers its type from whatever it's initialized with, but what you're initializing it with needs to know what its type is (in this case, the lambda closure needs to know the types it's capturing). Something of a chicken-and-egg problem.
On the other hand, a fully specified function object's type doesn't need to "know" anything about what is being assigned to it, and so the lambda's closure can likewise be fully informed about the types its capturing.
Consider this slight modification of your code and it may make more sense:
std::function<int(int, int)> sum;
sum = [term, next, &sum](int a, int b) -> int {
if (a > b)
return 0;
else
return term(a) + sum(next(a), b);
};
Obviously, this wouldn't work with auto. Recursive lambda functions work perfectly well (at least they do in MSVC, where I have experience with them), it's just that they aren't really compatible with type inference.
The trick is to feed in the lambda implementation to itself as a parameter, not by capture.
const auto sum = [term, next](int a, int b) {
auto sum_impl = [term, next](int a, int b, auto& sum_ref) mutable {
if (a > b) {
return 0;
}
return term(a) + sum_ref(next(a), b, sum_ref);
};
return sum_impl(a, b, sum_impl);
};
All problems in computer science can be solved by another level of indirection. I first found this easy trick at http://pedromelendez.com/blog/2015/07/16/recursive-lambdas-in-c14/
It does require C++14 while the question is on C++11, but perhaps interesting to most.
Here's the full example at Godbolt.
Going via std::function is also possible but can result in slower code. But not always. Have a look at the answers to std::function vs template
This is not just a peculiarity about C++,
it's directly mapping to the mathematics of lambda calculus. From Wikipedia:
Lambda calculus cannot express this as directly as some other
notations:
all functions are anonymous in lambda calculus, so we can't refer to a
value which is yet to be defined, inside the lambda term defining that
same value. However, recursion can still be achieved by arranging for a
lambda expression to receive itself as its argument value
With C++14, it is now quite easy to make an efficient recursive lambda without having to incur the additional overhead of std::function, in just a few lines of code:
template <class F>
struct y_combinator {
F f; // the lambda will be stored here
// a forwarding operator():
template <class... Args>
decltype(auto) operator()(Args&&... args) const {
// we pass ourselves to f, then the arguments.
return f(*this, std::forward<Args>(args)...);
}
};
// helper function that deduces the type of the lambda:
template <class F>
y_combinator<std::decay_t<F>> make_y_combinator(F&& f) {
return {std::forward<F>(f)};
}
with which your original sum attempt becomes:
auto sum = make_y_combinator([term,next](auto sum, int a, int b) -> int {
if (a>b) {
return 0;
}
else {
return term(a) + sum(next(a),b);
}
});
In C++17, with CTAD, we can add a deduction guide:
template <class F> y_combinator(F) -> y_combinator<F>;
Which obviates the need for the helper function. We can just write y_combinator{[](auto self, ...){...}} directly.
In C++20, with CTAD for aggregates, the deduction guide won't be necessary.
In C++23, with deducing this, you don't need a Y-combinator at all:
auto sum = [term,next](this auto const& sum, int a, int b) -> int {
if (a>b) {
return 0;
}
else {
return term(a) + sum(next(a),b);
}
}
I have another solution, but work only with stateless lambdas:
void f()
{
static int (*self)(int) = [](int i)->int { return i>0 ? self(i-1)*i : 1; };
std::cout<<self(10);
}
Trick here is that lambdas can access static variables and you can convert stateless ones to function pointer.
You can use it with standard lambdas:
void g()
{
int sum;
auto rec = [&sum](int i) -> int
{
static int (*inner)(int&, int) = [](int& _sum, int i)->int
{
_sum += i;
return i>0 ? inner(_sum, i-1)*i : 1;
};
return inner(sum, i);
};
}
Its work in GCC 4.7
To make lambda recursive without using external classes and functions (like std::function or fixed-point combinator) one can use the following construction in C++14 (live example):
#include <utility>
#include <list>
#include <memory>
#include <iostream>
int main()
{
struct tree
{
int payload;
std::list< tree > children = {}; // std::list of incomplete type is allowed
};
std::size_t indent = 0;
// indication of result type here is essential
const auto print = [&] (const auto & self, const tree & node) -> void
{
std::cout << std::string(indent, ' ') << node.payload << '\n';
++indent;
for (const tree & t : node.children) {
self(self, t);
}
--indent;
};
print(print, {1, {{2, {{8}}}, {3, {{5, {{7}}}, {6}}}, {4}}});
}
prints:
1
2
8
3
5
7
6
4
Note, result type of lambda should be specified explicitly.
You can make a lambda function call itself recursively. The only thing you need to do is to is to reference it through a function wrapper so that the compiler knows it's return and argument type (you can't capture a variable -- the lambda itself -- that hasn't been defined yet).
function<int (int)> f;
f = [&f](int x) {
if (x == 0) return 0;
return x + f(x-1);
};
printf("%d\n", f(10));
Be very careful not to run out of the scope of the wrapper f.
I ran a benchmark comparing a recursive function vs a recursive lambda function using the std::function<> capture method. With full optimizations enabled on clang version 4.1, the lambda version ran significantly slower.
#include <iostream>
#include <functional>
#include <chrono>
uint64_t sum1(int n) {
return (n <= 1) ? 1 : n + sum1(n - 1);
}
std::function<uint64_t(int)> sum2 = [&] (int n) {
return (n <= 1) ? 1 : n + sum2(n - 1);
};
auto const ITERATIONS = 10000;
auto const DEPTH = 100000;
template <class Func, class Input>
void benchmark(Func&& func, Input&& input) {
auto t1 = std::chrono::high_resolution_clock::now();
for (auto i = 0; i != ITERATIONS; ++i) {
func(input);
}
auto t2 = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(t2-t1).count();
std::cout << "Duration: " << duration << std::endl;
}
int main() {
benchmark(sum1, DEPTH);
benchmark(sum2, DEPTH);
}
Produces results:
Duration: 0 // regular function
Duration: 4027 // lambda function
(Note: I also confirmed with a version that took the inputs from cin, so as to eliminate compile time evaluation)
Clang also produces a compiler warning:
main.cc:10:29: warning: variable 'sum2' is uninitialized when used within its own initialization [-Wuninitialized]
Which is expected, and safe, but should be noted.
It's great to have a solution in our toolbelts, but I think the language will need a better way to handle this case if performance is to be comparable to current methods.
Note:
As a commenter pointed out, it seems latest version of VC++ has found a way to optimize this to the point of equal performance. Maybe we don't need a better way to handle this, after all (except for syntactic sugar).
Also, as some other SO posts have outlined in recent weeks, the performance of std::function<> itself may be the cause of slowdown vs calling function directly, at least when the lambda capture is too large to fit into some library-optimized space std::function uses for small-functors (I guess kinda like the various short string optimizations?).
Here is a refined version of the Y-combinator solution based on one proposed by #Barry.
template <class F>
struct recursive {
F f;
template <class... Ts>
decltype(auto) operator()(Ts&&... ts) const { return f(std::ref(*this), std::forward<Ts>(ts)...); }
template <class... Ts>
decltype(auto) operator()(Ts&&... ts) { return f(std::ref(*this), std::forward<Ts>(ts)...); }
};
template <class F> recursive(F) -> recursive<F>;
auto const rec = [](auto f){ return recursive{std::move(f)}; };
To use this, one could do the following
auto fib = rec([&](auto&& fib, int i) {
// implementation detail omitted.
});
It is similar to the let rec keyword in OCaml, although not the same.
In C++23 deducing this (P0847) will be added:
auto f = [](this auto& self, int i) -> int
{
return i > 0 ? self(i - 1) + i : 0;
}
For now its only available in EDG eccp and (partially) available in MSVC:
https://godbolt.org/z/f3E3xT3fY
This is a slightly simpler implementation of the fixpoint operator which makes it a little more obvious exactly what's going on.
#include <iostream>
#include <functional>
using namespace std;
template<typename T, typename... Args>
struct fixpoint
{
typedef function<T(Args...)> effective_type;
typedef function<T(const effective_type&, Args...)> function_type;
function_type f_nonr;
T operator()(Args... args) const
{
return f_nonr(*this, args...);
}
fixpoint(const function_type& p_f)
: f_nonr(p_f)
{
}
};
int main()
{
auto fib_nonr = [](const function<int(int)>& f, int n) -> int
{
return n < 2 ? n : f(n-1) + f(n-2);
};
auto fib = fixpoint<int,int>(fib_nonr);
for (int i = 0; i < 6; ++i)
{
cout << fib(i) << '\n';
}
}
C++ 14:
Here is a recursive anonymous stateless/no capture generic set of lambdas
that outputs all numbers from 1, 20
([](auto f, auto n, auto m) {
f(f, n, m);
})(
[](auto f, auto n, auto m) -> void
{
cout << typeid(n).name() << el;
cout << n << el;
if (n<m)
f(f, ++n, m);
},
1, 20);
If I understand correctly this is using the Y-combinator solution
And here is the sum(n, m) version
auto sum = [](auto n, auto m) {
return ([](auto f, auto n, auto m) {
int res = f(f, n, m);
return res;
})(
[](auto f, auto n, auto m) -> int
{
if (n > m)
return 0;
else {
int sum = n + f(f, n + 1, m);
return sum;
}
},
n, m); };
auto result = sum(1, 10); //result == 55
Here's the proof that a recursive lambda with a small body almost has the same performance like a usual recursive fuction which can call itself directly.
#include <iostream>
#include <chrono>
#include <type_traits>
#include <functional>
#include <atomic>
#include <cmath>
using namespace std;
using namespace chrono;
unsigned recursiveFn( unsigned x )
{
if( x ) [[likely]]
return recursiveFn( x - 1 ) + recursiveFn( x - 1 );
else
return 0;
};
atomic_uint result;
int main()
{
auto perf = []( function<void ()> fn ) -> double
{
using dur_t = high_resolution_clock::duration;
using urep_t = make_unsigned_t<dur_t::rep>;
high_resolution_clock::duration durMin( (urep_t)-1 >> 1 );
for( unsigned r = 10; r--; )
{
auto start = high_resolution_clock::now();
fn();
dur_t dur = high_resolution_clock::now() - start;
if( dur < durMin )
durMin = dur;
}
return durMin.count() / 1.0e9;
};
auto recursiveLamdba = []( auto &self, unsigned x ) -> unsigned
{
if( x ) [[likely]]
return self( self, x - 1 ) + self( self, x - 1 );
else
return 0;
};
constexpr unsigned DEPTH = 28;
double
tLambda = perf( [&]() { ::result = recursiveLamdba( recursiveLamdba, DEPTH ); } ),
tFn = perf( [&]() { ::result = recursiveFn( DEPTH ); } );
cout << trunc( 1000.0 * (tLambda / tFn - 1.0) + 0.5 ) / 10.0 << "%" << endl;
}
For my AMD Zen1 CPU with current MSVC the recursiveFn is about 10% faster. For my Phenom II x4 945 with g++ 11.1.x both functions have the same performance.
Keep in mind that this is almost the worst case since the body of the funtion is very small. If it is larger the part of the recursive function call itself is smaller.
You're trying to capture a variable (sum) you're in the middle of defining. That can't be good.
I don't think truely self-recursive C++0x lambdas are possible. You should be able to capture other lambdas, though.
Here is the final answer for the OP. Anyway, Visual Studio 2010 does not support capturing global variables. And you do not need to capture them because global variable is accessable globally by define. The following answer uses local variable instead.
#include <functional>
#include <iostream>
template<typename T>
struct t2t
{
typedef T t;
};
template<typename R, typename V1, typename V2>
struct fixpoint
{
typedef std::function<R (V1, V2)> func_t;
typedef std::function<func_t (func_t)> tfunc_t;
typedef std::function<func_t (tfunc_t)> yfunc_t;
class loopfunc_t {
public:
func_t operator()(loopfunc_t v)const {
return func(v);
}
template<typename L>
loopfunc_t(const L &l):func(l){}
typedef V1 Parameter1_t;
typedef V2 Parameter2_t;
private:
std::function<func_t (loopfunc_t)> func;
};
static yfunc_t fix;
};
template<typename R, typename V1, typename V2>
typename fixpoint<R, V1, V2>::yfunc_t fixpoint<R, V1, V2>::fix = [](tfunc_t f) -> func_t {
return [f](fixpoint<R, V1, V2>::loopfunc_t x){ return f(x(x)); }
([f](fixpoint<R, V1, V2>::loopfunc_t x) -> fixpoint<R, V1, V2>::func_t{
auto &ff = f;
return [ff, x](t2t<decltype(x)>::t::Parameter1_t v1,
t2t<decltype(x)>::t::Parameter1_t v2){
return ff(x(x))(v1, v2);
};
});
};
int _tmain(int argc, _TCHAR* argv[])
{
auto term = [](int a)->int {
return a*a;
};
auto next = [](int a)->int {
return ++a;
};
auto sum = fixpoint<int, int, int>::fix(
[term,next](std::function<int (int, int)> sum1) -> std::function<int (int, int)>{
auto &term1 = term;
auto &next1 = next;
return [term1, next1, sum1](int a, int b)mutable ->int {
if(a>b)
return 0;
else
return term1(a) + sum1(next1(a),b);
};
});
std::cout<<sum(1,10)<<std::endl; //385
return 0;
}
This answer is inferior to Yankes' one, but still, here it goes:
using dp_type = void (*)();
using fp_type = void (*)(dp_type, unsigned, unsigned);
fp_type fp = [](dp_type dp, unsigned const a, unsigned const b) {
::std::cout << a << ::std::endl;
return reinterpret_cast<fp_type>(dp)(dp, b, a + b);
};
fp(reinterpret_cast<dp_type>(fp), 0, 1);
You need a fixed point combinator. See this.
or look at the following code:
//As decltype(variable)::member_name is invalid currently,
//the following template is a workaround.
//Usage: t2t<decltype(variable)>::t::member_name
template<typename T>
struct t2t
{
typedef T t;
};
template<typename R, typename V>
struct fixpoint
{
typedef std::function<R (V)> func_t;
typedef std::function<func_t (func_t)> tfunc_t;
typedef std::function<func_t (tfunc_t)> yfunc_t;
class loopfunc_t {
public:
func_t operator()(loopfunc_t v)const {
return func(v);
}
template<typename L>
loopfunc_t(const L &l):func(l){}
typedef V Parameter_t;
private:
std::function<func_t (loopfunc_t)> func;
};
static yfunc_t fix;
};
template<typename R, typename V>
typename fixpoint<R, V>::yfunc_t fixpoint<R, V>::fix =
[](fixpoint<R, V>::tfunc_t f) -> fixpoint<R, V>::func_t {
fixpoint<R, V>::loopfunc_t l = [f](fixpoint<R, V>::loopfunc_t x) ->
fixpoint<R, V>::func_t{
//f cannot be captured since it is not a local variable
//of this scope. We need a new reference to it.
auto &ff = f;
//We need struct t2t because template parameter
//V is not accessable in this level.
return [ff, x](t2t<decltype(x)>::t::Parameter_t v){
return ff(x(x))(v);
};
};
return l(l);
};
int _tmain(int argc, _TCHAR* argv[])
{
int v = 0;
std::function<int (int)> fac =
fixpoint<int, int>::fix([](std::function<int (int)> f)
-> std::function<int (int)>{
return [f](int i) -> int{
if(i==0) return 1;
else return i * f(i-1);
};
});
int i = fac(10);
std::cout << i; //3628800
return 0;
}