I understand how lambda functions work. The problem is that the program calls the function recursiveFunction() before the compiler has deduced what 'auto' should be. The thing is, it's a recursive function so the function itself is in the definition.
#include <iostream>
using namespace std;
template <class T>
class Class {
public:
int foo(int x);
};
template <class T>
int Class<T>::foo(int x) {
auto recursiveFunction = [=](int n)->int {
if (n <= 1) return 1;
else return n*recursiveFunction(n-1);
};
return recursiveFunction(x);
}
int main() {
Class<int> c;
cout << c.foo(5) << endl;
return 0;
}
I've also implemented this using a class using templates in case that factors into the problem.
Here's the error message:
main.cpp: In instantiation of 'int Class<T>::foo(int) [with T = int]':
main.cpp:21:20: required from here
main.cpp:14:40: error: use of 'recursiveFunction' before deduction of 'auto'
else return n*recursiveFunction(n-1);
Thanks!
Answered here:
The second snippet runs into [dcl.spec.auto]/10:
If the type of an entity with an undeduced placeholder type is needed to determine the type of an expression, the program is ill-formed.
The type of foo is needed to determine the type of the expression foo within the lambda body, but at that point you haven't deduced foo's type yet, so the program is ill-formed.
Further references:
lambda capture during initialization should be an error
"a variable declared with an auto specifier cannot appear in its own initializer"
Fix: https://godbolt.org/z/np3ULe
#include <iostream>
#include <functional>
template <class T>
class Class {
public:
int foo(int x);
};
template <class T>
int Class<T>::foo(int x) {
std::function<int(int)> fac = [&fac](int n) -> int {
if (n <= 1)
return 1;
else
return n * fac(n - 1);
};
return fac(x);
}
int main() {
Class<int> c;
std::cout << c.foo(5) << std::endl;
return 0;
}
Couple possible answers:
type-erasure; you don't actually need to know the type of recursiveFunction, just enough to have pinned down its signature.
So you could just do without the problematic auto and associated deduction, and promise to know the type in advance.
template <class T>
int Class<T>::foo(int x) {
std::function<int(int)> recursiveFunction;
recursiveFunction = [=](int n)->int {
if (n <= 1) return 1;
else return n*recursiveFunction(n-1);
};
return recursiveFunction(x);
}
If this wasn't just an oversimplified example, you don't appear to actually be capturing any state, so you could just use a normal recursive function instead of a lambda.
namespace {
int recursiveFunction(int) {
if (n <= 1) return 1;
else return n*recursiveFunction(n-1);
}
}
int Class<T>::foo(int x) {
return recursiveFunction(x);
}
If the lambda aspect was actually important, you're looking for the "Y combinator". Which is not very straightforward in C++, but something like:
#include <iostream>
#include <functional>
template <class T>
class Class {
public:
int foo(int x);
};
template<class F>
struct function_traits;
template<class R, class T>
struct function_traits<R(T)> {
typedef R return_type;
typedef T arg_type;
};
// function pointer
template<class R, class... Args>
struct function_traits<R(*)(Args...)> : public function_traits<R(Args...)>{}};
template <typename Signature>
auto y (std::function<typename function_traits<Signature>::return_type(typename function_traits<Signature>::arg_type, std::function<Signature>)> f)
-> std::function<Signature>
{
return [f](typename function_traits<Signature>::arg_type n) -> typename function_traits<Signature>::return_type { return f(n,y(f)); };
}
template <class T>
int Class<T>::foo(int x) {
return y<int(int)>([=](int n, auto recursiveFunction) -> int {
if (n <= 1) return 1;
else return n*recursiveFunction(n-1);
})(5);
}
int main() {
Class<int> c;
std::cout << c.foo(5) << std::endl;
return 0;
}
If you want to avoid std::function, you might do (requires C++14 for generic lambda):
int Class<T>::foo(int x) {
auto recursiveFunction = [](auto recFunc, int n) -> int
{
if (n <= 1) return 1;
else return n * recFunc(recFunc, n - 1);
};
return recursiveFunction(recursiveFunction, x);
}
Demo
Related
I have the following concept:
template <typename T>
concept FunctorInt = requires(T a, int b) {
a.operator()(b); //require the () operator with a single int parameter.
};
I use this in the following function:
template <FunctorInt functor_t>
void for_each_sat_lit(const int ClauseIndex, functor_t functor) {
auto LitIndex = -1;
uint32_t Count = h_SatisfiedLitCount[ClauseIndex];
if constexpr (!satlit) { Count = h_LiteralsInClauseCount[ClauseIndex] - Count; }
for (uint32_t dummy = 0; dummy < Count; dummy++) {
LitIndex = NextSetBit(h_SATLiteralBits[ClauseIndex], LitIndex);
functor(LitIndex); //LitIndex must be an int.
}
}
This compiles. However, when I try and break the code by changing the concept to
template <typename T>
concept FunctorInt = requires(T a, float b) {
a.operator()(b); //I intend to require the () operator with a single float parameter.
};
It still compiles, meaning it did not constrain the functor at all.
How do I constrain a functor so that it can only have a single int parameter?
MSVC: concepts.cpp
#include <concepts>
template <typename T>
concept FunctorInt = requires(T a, int b) {
a.operator()(b); //require the () operator with a single int parameter.
};
template <typename T>
concept FunctorFloat = requires(T a, float b) {
a.operator()(b); //require the () operator with a single float parameter.
};
void Loop(FunctorInt auto functor) {
for (auto i = 0; i < 10; i++) {
functor(i);
}
}
void LoopShouldNotCompile(FunctorFloat auto functor) {
for (auto i = 0; i < 10; i++) {
functor(i); //<< i is not a float.
}
}
int main(const int argc, const char* argv[]) {
Loop( [](int a){ printf("%i", a); });
LoopShouldNotCompile([](float a){ printf("%f", a); });
}
If I change the definitions of FunctorInt and FunctorFloat using std::invocable, the same problem persists:
concept FunctorInt = std::invocable<int>;
concept FunctorFloat = std::invocable<float>;
Everything still compiles, whereas it should give a compile error on LoopShouldNotCompile.
UPDATE:
I settled on:
template <typename T>
concept FunctorInt =
requires() { [](void(T::*)(int) const){}(&T::operator()); }
|| requires() { [](void(T::*)(int) ){}(&T::operator()); };
Which creates a functor that only allows a single int parameter and doesn't care about const-correctness.
If you want to block a function from accepting any other type that you want, you can use a type matching function template... e.g.
#include <concepts>
template <typename T>
requires std::same_as<T,float>
void func([[maybe_unused]]T f) {}
int main() {
//func(1); // doesn't compile
func(1.0f); // works
//func(1.0); // NB: fails again, because float!=double
}
edit: shorter
void func([[maybe_unused]]std::same_as<float> auto f) {}
Your concept check if the type can be called with an int
but you cannot control promotion/conversion which happens before.
You can check signature of T::operator(), but then previous valid cases (as overload, template function, no exact function but similar (const, volatile, ...)) might no longer work.
For example:
template <typename T>
concept FunctorInt = requires() {
[](void(T::*)(int) const){}(&T::operator());
};
void Loop(FunctorInt auto functor) { /**/ }
int main() {
Loop([](int a){ printf("%i", a); });
Loop([](float a){ printf("%f", a); }); // Not compile
}
Demo
I would like to know how to convert function composition, but without using lambda. Below is the original code from https://stackoverflow.com/a/50035197.
template<class Root, class... Branches> auto comp(Root &&root, Branches &&... branches) {
return [root, branches...](auto &&...args) {
return root(branches(std::forward<decltype(args)>(args)...)...);
};
}
int f(int x, int y) { return x + y; }
int g(int x) { return x * 19; }
int h(int x) { return x + 2; }
#include <iostream>
int main() {
auto fgh = comp(f, g, h);
std::cout << fgh(2) << '\n';
}
I tried to mimic the comp function without using lambdas, but failed to compile:
template<class Root, class... Branches>
class compose2 {
Root root;
tuple<Branches...> branches;
public:
compose2(Root r, Branches... br) : root(r), branches(br...) {};
template <class... Args>
decltype(auto) operator()(Args... args) {
return root(branches((args)...)...); // compile error, because a tuple is not a parameter pack
}
};
I know that parameter pack cannot be a member variable, so my first thought was to use a tuple for storing the functors (branches), but I'm stuck here. So the question is, how to expand branches as in comp?
I have many functions q1, q2, q3, etc., each with a different return type (int, int64_t, std::string, etc.).
I also have a print_result function that prints out their results (and the time they take to run, but trimmed here for simplicity):
template <typename T>
void print_result(T (*func)()) {
T res = func();
std::cout << res << std::endl;
}
I also have big switch statement to print the result for each of the functions:
switch (question_num) {
case 1: print_result(q1); break;
case 2: print_result(q2); break;
case 3: print_result(q3); break;
// ...
}
Objective: I would like to replace this switch statement with a template function, to avoid copying each line every time I add a new function.
I have tried to look at C++ template instantiation: Avoiding long switches, but I'm new to template metaprogramming, so not sure how to handle this exactly.
My current attempt that doesn't compile:
template <<int, typename> ...> struct FuncList {};
template <typename T>
bool handle_cases(int, T, FuncList<>) {
// default case
return false;
}
template <<int I, typename T> ...S>
bool handle_cases(int i, T (*func)(), FuncList<T, S...>) {
if (I != i) {
return handle_cases(i, func, FuncList<S...>());
}
print_result(func);
return true;
}
template <typename ...S>
bool handle_cases(int i, T (*func)()) {
return handle_cases(i, func, FuncList<S...>());
}
// ...
bool res = handle_cases<
<1, q1>, <2, q2>, <3, q3>
>(question_num);
// ...
My ideal way of using this template is shown at the last line there.
Note that the mappings from the function number to the function is provided there. The function numbers are fixed, i.e. q1 maps to the constant 1 and that won't change at runtime.
The compilation error (it might be rather basic but I really don't know much about metaprogramming):
error: expected unqualified-id before ‘<<’ token
17 | template <<int, typename> ...> struct FuncList {};
| ^~
If you can use c++17, here's a "simplified" version of #Klaus's approach. Instead of using a had-made recursive structure, you could use a c++17 fold-expression:
template<auto... Funcs, std::size_t... I>
bool select_case(std::size_t i, std::integer_sequence<std::size_t, I...>) {
return ([&]{ if(i == I) { print_result(Funcs); return true; } return false; }() || ... );
}
template<auto... Funcs>
struct FuncSwitch {
static bool Call(std::size_t i) {
return select_case<Funcs...>(i, std::make_index_sequence<sizeof...(Funcs)>());
}
};
The idea is to wrap each of Funcs in a lambda such that only the function corresponding to the index passed is called. Note that the || in the fold expression short-circuits.
Would be used like this:
float q0() { return 0.f; }
int q1() { return 1; }
std::string q2() { return "two"; }
int main() {
bool success = FuncSwitch<q0, q1, q2>::Call(1);
}
See here for a complete example.
I've got a different proposal:
Use an std::array instead of switch (or std::map if the switch cases are non-continuous, std::array has O(1) access time, std::map O(log(n)) and switch O(n).
Use std::function and std::bind to bind your functions you want to call to a functor object
use the index into the array to call the function
Use placeholders if you need to pass additional data
#include <iostream>
#include <functional>
template <typename T>
void print_result(T (*func)()) {
T res = func();
std::cout << res << std::endl;
}
int int_function() {
return 3;
}
double double_function() {
return 3.5;
}
std::array<std::function<void()>, 2> functions({
std::bind(print_result<int>, int_function),
std::bind(print_result<double>, double_function),
});
int main() {
functions[0]();
functions[1]();
return 0;
}
Output:
3
3.5
See: Why does std::function can implicit convert to a std::function which has more parameter?
Update:
With parameter passing:
#include <iostream>
#include <functional>
template <typename T>
void print_result(T (*func)(int), int value) {
T res = func(value);
std::cout << res << std::endl;
}
int int_function(int value) {
return 3 * value;
}
double double_function(int value) {
return 3.5 * value;
}
std::array<std::function<void(int)>, 2> functions({
std::bind(print_result<int>, int_function, std::placeholders::_1),
std::bind(print_result<double>, double_function, std::placeholders::_1),
});
int main() {
functions[0](10);
functions[1](11);
return 0;
}
Output:
30
38.5
You may like a version which do not need any kind of runtime containers, did not generate any objects in between and even do not generate a data table and generates very less code and is also easy to use:
// Example functions
int fint() { return 1; }
double fdouble() { return 2.2; }
std::string fstring() { return "Hallo"; }
// your templated result printer
template < typename T>
void print_result( T parm )
{
std::cout << "The result of call is " << parm << std::endl;
}
// lets create a type which is able to hold functions
template < auto ... FUNCS >
struct FUNC_CONTAINER
{
static constexpr unsigned int size = sizeof...(FUNCS);
};
// and generate a interface to switch
template < unsigned int, typename T >
struct Switch_Impl;
template < unsigned int IDX, auto HEAD, auto ... TAIL >
struct Switch_Impl< IDX, FUNC_CONTAINER<HEAD, TAIL...>>
{
static void Do( unsigned int idx )
{
if ( idx == IDX )
{
// Your function goes here
print_result(HEAD());
}
else
{
if constexpr ( sizeof...(TAIL))
{
Switch_Impl< IDX+1, FUNC_CONTAINER<TAIL...>>::Do(idx);
}
}
}
};
// a simple forwarder to simplify the interface
template < typename T>
struct Switch
{
static void Do(unsigned int idx )
{
Switch_Impl< 0, T >::Do( idx );
}
};
// and lets execute the stuff
int main()
{
using FUNCS = FUNC_CONTAINER< fint, fdouble, fstring >;
for ( unsigned int idx = 0; idx< FUNCS::size; idx++ )
{
Switch<FUNCS>::Do(idx);
}
}
Given you "current attempt"... it seems to me that you could write a handle_cases struct/class almost as follows
struct handle_cases
{
std::map<int, std::function<void()>> m;
template <typename ... F>
handle_cases (std::pair<int, F> const & ... p)
: m{ {p.first, [=]{ print_result(p.second); } } ... }
{ }
void operator() (int i)
{ m[i](); }
};
with a map between an integer and a lambda that call print_result with the function and an operator() that call the requested lambda, given the corresponding index.
You can create an object of the class as follows (unfortunately I don't see a way to avoid the std::make_pair()s)
handle_cases hc{ std::make_pair(10, q1),
std::make_pair(20, q2),
std::make_pair(30, q3),
std::make_pair(40, q4) };
and using it as follows
hc(30);
The following is a full compiling example
#include <functional>
#include <map>
#include <iostream>
template <typename T>
void print_result (T(*func)())
{
T res = func();
std::cout << res << std::endl;
}
struct handle_cases
{
std::map<int, std::function<void()>> m;
template <typename ... F>
handle_cases (std::pair<int, F> const & ... p)
: m{ {p.first, [=]{ print_result(p.second); } } ... }
{ }
void operator() (int i)
{ m[i](); }
};
char q1 () { return '1'; }
int q2 () { return 2; }
long q3 () { return 3l; }
long long q4 () { return 4ll; }
int main ()
{
handle_cases hc{ std::make_pair(10, q1),
std::make_pair(20, q2),
std::make_pair(30, q3),
std::make_pair(40, q4) };
hc(30);
}
I have the following code:
#include <iostream>
using namespace std;
template <class T>
int get_num(int k) {
return k + 3;
}
float get_num(float k) {
return k + 3;
}
template <class T1, class T2>
void function(T1 (*callback)(T2), T2 arg) {
callback(arg);
}
int main() {
// your code goes here
function(get_num, 3);
return 0;
}
I need to call the get_num() function with an int argument. But compiler gets this error:
prog.cpp: In function ‘int main()’: prog.cpp:21:21: error: no matching
function for call to ‘function(<unresolved overloaded function type>,
int)’ function(get_num, 3);
^ prog.cpp:15:6: note: candidate: template<class T1, class T2> void function(T1 (*)(T2), T2) void function(T1
(*callback)(T2), T2 arg) {
^~~~~~~~ prog.cpp:15:6: note: template argument deduction/substitution failed: prog.cpp:21:21: note: couldn't deduce
template parameter ‘T1’ function(get_num, 3);
How can it be done ?
After removing template <class T> from int get_num(int) to get a normal overload set, you can use Some programmer dude’s answer.
In this answer I want to elaborate how you can still use a function pointer based parameter.
If you switch the arguments to function at least gcc is able to deduce it:
template <typename T, typename U>
void function2(T arg, U(*callback)(T)) {
callback(arg);
}
clang doesn’t like it when you use U there, so if your return types will always be the same as your arguments, you can use T twice:
template <typename T>
void function2(T arg, T(*callback)(T)) {
callback(arg);
}
To resolve disambiguities like the one in your error message in general, you can also do the overload resolution manually with static_cast:
function(static_cast<float(*)(float)>(&get_num), 3.0f);
function(static_cast<int(*)(int)>(&get_num), 3);
One problem is that you have different types for return-type and argument-type for function, but in reality both are the same.
That means you could do something like
template<typename T, typename F = T(T)>
void function(F callback, T arg)
{
callback(arg);
}
The template argument F is just to simplify the callback argument declaration.
You have a template <class T> in front of your int get_num(int k). Lets assume for a moment it isnt there, then this works:
Sometimes you cannot change the function into a template, but need to work with function pointers to a function that has several overloads. The way to choose the right overload is to specify the type of the function pointer (because for different overloads the function pointers are of different type).
typedef int (* int_get_num_t)(int);
int main() {
int_get_num_t correct_overload = get_num;
function(correct_overload, 3);
return 0;
}
In case the int get_num(int k) is really supposed to be a template (then why the float one isnt?) then you simply have to pick the template version:
int_get_num_t correct_overload = get_num<int>;
where actually you could pass any type instead of int as your template get_num always takes an int and returns an int irrespective of the template parameter.
And finally... you actually dont need the second overload for get_num but you need only one template. And in that case you still need to pick the right template to get the function pointer:
template <typename T>
T get_num(T k) { return k + 3; }
template <class T1, class T2>
void function(T1 (*callback)(T2), T2 arg) {
callback(arg);
}
int main() {
int_get_num_t correct_overload = get_num<int>;
function(correct_overload, 3);
return 0;
}
Here's the one using the C++ functors.
#include <iostream>
using namespace std;
template<class T>
struct get_num : public std::unary_function<T,T>
{
T operator()(const T& k) {
return k+3;
}
};
template< class T1, class T2 >
void function( T1 fun, T2 arg)
{
fun(arg);
cout << fun(arg) << endl;
}
int main()
{
function(get_num<int>(), 3);
return 0;
}
The following code will work:
#include <iostream>
using namespace std;
template<typename T>
int get_num(int k) {
return k + 3;
}
float get_num(float k) {
return k + 3;
}
template<typename T1, typename T2> // Maybe here you want the `typename`, not the `class`
void f(T1 (*callback)(T2), T2 arg) {
callback(arg);
}
int main() {
// your code goes here
f(get_num<int>, 3); // The key point is here!
return 0;
}
The reason you get the compiling error is the compiler could not deduce the type T if you just use get_num, because all the arguments are nothing with the type T.
You have to specify the type of function
#include <iostream>
#include <string>
int get_num(int k) {
return k + 3;
}
float get_num(float k) {
return k + 3;
}
std::string get_num (double a)
{
return "this is a string " + std::to_string(a);
}
template <class T1, class T2>
using callback = T1(*)(T2);
template <class T1, class T2>
void function(callback<T1, T2> function, T2 arg) {
std:: cout << function(arg) << std::endl;
}
int main() {
// your code goes here
function<int, int>(get_num, 3);
function<std::string, double>(get_num, 3);
system("pause");
return 0;
}
Why 2 different template arguments? -The OP's question is not about optimization, it is about
How to pass the specific callback to a template function?
So, this is one of many implementations, solving the specific error.
I allowed myself to simplify a bit Your code. This should work fine:
#include <iostream>
using namespace std;
template <class T>
T get_num(T k) {
return k + 3;
}
template <class T1, class T2>
void function(T1 callback, T2 arg) {
callback(arg);
}
int main() {
function(get_num<int>, 3);
return 0;
}
I want to provide an solution which differs a bit.
I explain it inside the code to make it hopefully more comfortable to read and understand:
// create a helper class,
// which collects all callable classes to build one callable object later
template<class... Ts> struct funcs : Ts... { using Ts::operator()...; };
template<class... Ts> funcs(Ts...) -> funcs<Ts...>;
// instead of free functions, build objects with methods
// and use operator() instead of function names.
// this makes it easier to "understand" that this will be an callable object
struct Func1
{
int operator()(int k) {
return k + 3;
}
};
struct Func2
{
float operator()(float k) {
return k + 3;
}
};
// adapt your code to this:
template <class T1, class T2>
auto function(T1 callback, T2 arg) {
return callback(arg);
}
// and finaly you can use it this way, also with return types
// the central hack is:
// funcs{ Func1(), Func2() }
// this will generate a callable object with all the overloads
// from the inserted callable objects
int main() {
// your code goes here
std::cout << function(funcs{ Func1(), Func2() }, 3) << std::endl;
std::cout << function(funcs{ Func1(), Func2() }, (float)7.999) << std::endl;
return 0;
}
I get this compile error with the latest VC++ compiler (Nov 2012 CTP) when using static member function pointer as template argument:
error C2027: use of undefined type 'wrapper<int (int,int),int A::f1(int,int)>'
But when using free function, everything works ok.
I looked up some similar bugs in g++( pointer to static member function is "invalid" as a template argument for g++ ), but there it explicitly states that argument is invalid. What is so different about static functions?
I'm casting the function to void(*)(void) because construct like <typename T_Ret, typename... T_Args, T_Ret(*)(T_Args...)> don't compile for some other urelated reasons.
struct A
{
static int f1(int a, int b)
{
return a + b;
}
};
int f2(int a, int b)
{
return a + b;
}
template <typename Sig, void(*fnc)(void)>
struct wrapper;
template <void(*fnc)(void), typename T_Ret, typename... T_Args>
struct wrapper<T_Ret (T_Args...), fnc>
{
static bool apply()
{
// get some ints here
int a = 1;
int b = 2;
typedef T_Ret (fnc_ptr*)(T_Args...);
int res = ( (fnc_ptr)fnc )(a, b);
// do smth with result
res;
return true; // or false
}
};
int main()
{
bool res;
res = wrapper<decltype(A::f1), (void(*)(void))A::f1>::apply(); // error
res = wrapper<decltype(f2), (void(*)(void))f2>::apply(); // compiles ok
return 0;
}
EDIT:
Ok, I narrowed the issue to decltype.
When I write the type explicitly, everything works:
res = wrapper<int(int, int), (void(*)(void))A::f1>::apply(); // compiles ok
EDIT:
Looks like it's a compiler bug: http://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Core-C-/STLCCSeries6#c634886322325940618
Workaround:
Change decltype(A::f1) to decltype(&A::f1) which changed its output from int(int, int) to int (__cdecl *)(int,int). And change
template <void(*fnc)(void), typename T_Ret, typename... T_Args>
struct wrapper<T_Ret (T_Args...), fnc>
to
template <void(*fnc)(void), typename T_Ret, typename... T_Args>
struct wrapper<T_Ret (*)(T_Args...), fnc>
Working code:
struct A
{
static int f1(int a, int b)
{
return a + b;
}
};
template <typename Sig, void(*fnc)(void)>
struct wrapper;
template <void(*fnc)(void), typename T_Ret, typename... T_Args>
struct wrapper<T_Ret (*)(T_Args...), fnc>
{
static bool apply()
{
// get some ints here
int a = 1;
int b = 2;
typedef T_Ret (*fnc_ptr)(T_Args...);
int res = ( (fnc_ptr)fnc )(a, b);
// do smth with result
res;
return true; // or false
}
};
int main()
{
bool res;
res = wrapper<decltype(&A::f1), (void(*)(void))A::f1>::apply();
return 0;
}
You could try something like this:
#include <iostream>
using namespace std;
struct A
{
static int f1(int a, int b)
{
return a + b;
}
};
int f2(int a, int b)
{
return a + b;
}
template <typename T, T X>
struct wrapper
{
template <typename... Args>
static bool value(Args... blargs)
{
return X(blargs...) == 3;
}
};
int main()
{
bool res;
res = wrapper<decltype(&A::f1), &A::f1>::value(1,2);
cout << res << endl;
return 0;
}
But seriously, this is so much easier:
#include <iostream>
using namespace std;
int main()
{
bool res;
res = A::f1(a, b) == 3;
cout << res << endl;
return 0;
}