I want to write a variadic template or const expressions which 1) execute a template functor N times and 2) accumulates the result. I wrote a small example which actually fails compilation as soon as I move the function which gets executed into a template functor. I have the feel I am close to the solution, but maybe I am wrong.
#include <iostream>
#include <string>
struct F {
template <int id>
static int run(int val) {
return id * val;
}
};
template<unsigned int n>
struct accumulate_for
{
template <class Funct>
static int get(int val) {
return
(
accumulate_for<n-1>::get(val)
+
Funct::run<n>(val)
);
}
};
template<>
struct accumulate_for<0>
{
template <class Funct>
static int get(int val) {
return 0;
}
};
int main()
{
std::cout << accumulate_for<3>::get<F>(1) << std::endl;
}
accumulate_for<n>::get is a member function template, so you have to specify template argument when calling it.
You need to use template keyword to indicate that get and run (which are both dependent names) are templates.
e.g.
template<unsigned int n>
struct accumulate_for
{
template <class Funct>
static int get(int val) {
return
(
accumulate_for<n-1>::template get<Funct>(val)
// ~~~~~~~~ ~~~~~~~
+
Funct::template run<n>(val)
// ~~~~~~~~
);
}
};
LIVE
For more info about the usage of the template keyword, refer to Where and why do I have to put the “template” and “typename” keywords?
Related
I have a template class, with an internal method that is itself templated.
Consider the following minimal working example
#include <functional>
template<typename T>
class P{
public:
template <typename U>
P<U> call(std::function< P<U> (T)> f){
return f(return_value);
}
T return_value;
};
P<int> foo() {
P<int> value = P<int>();
return value;
}
P<float> bar(int arg) {
return P<float>();
}
int main()
{
auto res = foo().call<float>(bar);
return 0;
}
As you can see in the main function, the compiler forces me to to specify the float type for calling the call() function, eventhough the type should be obvious from passing over the bar() function, that specifies the float type.
Is it somehow possible to deduct the type so that the code in the main function can be simplified to the following statement:
auto res = foo().call(bar);
std::function is not the type that you should use whenever you want to pass a function around. std::function is a type that uses type erasure to be able to store different types of callables in one type. If you don't need that then you need no std::function:
#include <functional>
template<typename T>
class P{
public:
template <typename F>
auto call(F f){
return f(return_value);
}
T return_value{}; // don't forget to initialize !
};
P<int> foo() {
P<int> value = P<int>();
return value;
}
P<float> bar(int arg) {
return P<float>();
}
int main()
{
auto res = foo().call(bar);
return 0;
}
Using partial specializatzion you can get the return type of bar and you can get the float from P<float>:
#include <type_traits>
#include <iostream>
template <typename T> class P;
// get return type from function
template <typename T> struct return_type;
template <typename R,typename...args>
struct return_type<R(args...)> { using type = R; };
// get T from P<T>
template <typename P> struct P_arg;
template <typename T> struct P_arg< P<T> > { using type = T; };
// combine both
template <typename F>
struct get {
using type = typename P_arg<typename return_type<F>::type >::type;
};
template<typename T>
class P{
public:
template <typename F>
auto call(F f){
return f(return_value);
}
T return_value{};
};
P<float> bar(int arg) {
return P<float>();
}
int main()
{
std::cout << std::is_same_v< get<decltype(bar)>::type,float>;
return 0;
}
Though that does not really help here, because you cannot use it to decalre the return type of P::call, as it requires P<float> to be already complete.
I'm working on a C++11 wrapper around a C api. The C api offers a bunch of getters for various types, with a different name for each type. Values are retrieved by array of a given size, known at compilation.
I want to give the type and the array size by template, to call the right function.
#include <string>
#include <iostream>
template <typename T>
struct make_stop {
constexpr static bool value = false;
};
class Foo
{
public:
Foo() : i(42) {}
template<typename T, size_t n>
T get();
private:
int i = 0;
};
template<typename T, size_t n>
T Foo::get() { static_assert(make_stop<T>::value); return T(); }
template<int, size_t n>
int Foo::get() { return i + n; }
int main() {
Foo foo;
int i = foo.get<int, 4>();
double f = foo.get<double, 2>();
return 0;
}
But it fails to match the right function
main.cpp:26:5: error: no declaration matches 'int Foo::get()'
int Foo::get() { return i + n; }
^~~
main.cpp:15:7: note: candidate is: 'template<class T, long unsigned int n> T Foo::get()'
T get();
its a bit vauge from your question, but assuming you are wanting to index into some c- arrays and return the value at I you can't specialize function templates like you want, but you can use some tags instead, something like..
class Foo
{
public:
Foo() : is{1,2,3,4,5,6,7,8,9,10},ds{1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9,10.1} {}
template <typename T> struct type_c{};
template <size_t I> struct int_c{};
template<typename T,size_t I>
auto get()
{ return get_impl(type_c<T>(),int_c<I>()); }
private:
template <size_t I>
auto get_impl(type_c<int>,int_c<I>)
{ return is[I]; }
template <size_t I>
auto get_impl(type_c<double>,int_c<I>)
{ return ds[I]; }
int is[10];
double ds[10];
};
int main() {
Foo foo;
int i = foo.get<int,0>();
double d = foo.get<double,2>();
std::cout << i << " " << d << std::endl;
return 0;
}
Demo
If I understood you correctly you want to partially specialize get for T. Unfortunately partial specialization for methods is not allowed by the standard. You can however get around this with a static method on a class templated by T and specializing the class.
Like this:
template <class T> struct Foo_helper;
struct Foo
{
Foo() : i{42} {}
template<class T, std::size_t N>
T get()
{
return Foo_helper<T>::template get<N>(*this);
}
int i = 0;
};
template <class T> struct Foo_helper {};
// specialize Foo_helper for each type T you wish to support:
template <> struct Foo_helper<int>
{
template <std::size_t N>
static int get(const Foo& foo) { return foo.i + N; }
};
template <> struct Foo_helper<double>
{
template <std::size_t N>
static double get(const Foo& foo) { return foo.i + N; }
};
int main()
{
Foo foo{};
int i = foo.get<int, 4>();
double d = foo.get<double, 2>();
}
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;
}
Suppose I have a template function:
template<typename T>
T produce_5_function() { return T(5); }
How can I pass this entire template to another template?
If produce_5_function was a functor, there would be no problem:
template<typename T>
struct produce_5_functor {
T operator()() const { return T(5); }
};
template<template<typename T>class F>
struct client_template {
int operator()() const { return F<int>()(); }
};
int five = client_template< produce_5_functor >()();
but I want to be able to do this with a raw function template:
template<??? F>
struct client_template {
int operator()() const { return F<int>(); }
};
int five = client_template< produce_5_function >()();
I suspect the answer is "you cannot do this".
I suspect the answer is "you cannot do this".
Yes, that is the case, you cannot pass a function template as a template argument. From 14.3.3:
A template-argument for a template template-parameter shall be the
name of a class template or an alias template, expressed as
id-expression.
The template function needs to be instantiated before you pass it to the other template. One possible solution is to pass a class type that holds a static produce_5_function like so:
template<typename T>
struct Workaround {
static T produce_5_functor() { return T(5); }
};
template<template<typename>class F>
struct client_template {
int operator()() const { return F<int>::produce_5_functor(); }
};
int five = client_template<Workaround>()();
Using alias templates, I could get a little closer:
template <typename T>
T produce_5_functor() { return T(5); }
template <typename R>
using prod_func = R();
template<template<typename>class F>
struct client_template {
int operator()(F<int> f) const { return f(); }
};
int five = client_template<prod_func>()(produce_5_functor);
How about wrapping that function?
template<typename T>
struct produce_5_function_wrapper {
T operator()() const { return produce_5_function<T>(); }
};
Then you can use the wrapper instead of the function:
int five = client_template< produce_5_function_wrapper >()();
Using the template function alone will not work, there's no such thing as "template template functions".
I would like to be able to name to a templated function in a template.
Since one can name a templated class using the "template template" syntax, and since one can name a function using the "function pointer" syntax, I was wondering whether there is a syntax (or a proposal) to name a function in a template without specifying to templates.
template<typename t_type>
struct A {
t_type value;
};
template<template<typename> class t_type>
struct B {
t_type<int> value;
};
template<int added>
constexpr int C (int value) {
return value + added;
}
template<int (*function)(int)>
constexpr int D (int value) {
return function(value);
}
// GOAL: Template argument referring to templated function
/*template<template<int> int (*function)(int)>
constexpr int E (int value) {
return function<1>(value);
}*/
int main() {
B<A> tt_good;
int fp_good = D< &C<1> >(0);
/*int fp_fail = E< &C >(0);*/
return 0;
}
One possible work-around for anyone interested in this functionality to first wrap the function D in a struct with a call method named (for example) "method", pass the struct into E as a "template template" parameter, and then call "method" in E.
The reason that I don't like this approach is that it requires a wrapper structure for every variadic function that might be used in this way.
Unfortunately, you cannot pass function templates as template parameters. The closest you can get is by using generic functors:
#include <iostream>
template <typename F>
void call(F f)
{
f("hello, world\n");
}
int main()
{
call([](auto value) { std::cout << value; });
}
If you don't have C++14 generic lambdas, you can write your own functors by hand:
#include <iostream>
template <typename F>
void call(F f)
{
f("hello, world\n");
}
struct print
{
template <typename T>
void operator()(T value) const
{
std::cout << value;
}
};
int main()
{
call(print());
}