consider this simple and pointless code.
#include <iostream>
struct A {
template<int N>
void test() {
std::cout << N << std::endl;
}
};
int main() {
A a;
a.test<1>();
}
It is a very simple example of a function template. What if however, I wanted to replace A::test with an overloaded operator() to make it a functor?
#include <iostream>
struct A {
template<int N>
void operator()() {
std::cout << N << std::endl;
}
};
int main() {
A a;
a<1>(); // <-- error, how do I do this?
}
Certainly if the operator() took parameters which were dependent on the template, the compiler could possibly deduce the template. But I just can't figure out the proper syntax to specify template parameters with a parameterless functor.
Is there a proper way to do this?
Obviously, this code would work since it bypasses the functor syntax:
a.operator()<1>();
but that kinda defeats the purpose of it being a functor :-P.
You can only call
a.operator()<1>();
but that would not be using a functor. Functors need a non template operator(), as they must be able to be called as varname() and that won't work with your code.
To make it a real functor change your code a template class (functors are classes):
#include <iostream>
template<int N>
struct A {
void operator()() {
std::cout << N << std::endl;
}
};
int main() {
A<1> a;
a();
}
There's not another "direct" way I know other than the:
a.operator()<1>();
syntax. If you're open to changing the code, moving the template parameter to the class would work, or using a (boost|tr1)::bind to make a (boost|tr1)::function object.
You are trying to pass a template parameter to an instance of an object, which as far as I know is not allowed. You can only pass templates parameters to template functions or template objects.
a.test<1>(); and a.operator()<1>(); work because they are serving as template functions.
Use boost::bind (check out boost libraries) to fix it though.
struct A {
void operator()(int n) {
std::cout << n << std::endl;
}
};
int main(int argc, char* argv[]) {
A a;
boost::function<void()> f = boost::bind<void>(a, 1);
f(); // prints 1
return 0;
}
And you don't even have to mess with templates!
You're stuck. Have you considered something like
struct A {
template<int N>
struct B
{
void operator()()
{ std::cout << N << std::endl; }
};
template<int N>
B<N> functor() {return B<N>();}
};
int main()
{
A a;
a.functor<1>()();
}
Nope, there's no way around it. Like you said, you have to either call the operator explicitly (which defeats the purpose), or the template arguments must be able to be deduced by the compiler.
Related
A reference to array parameter is useful because it prevents decay, allowing you to deduce the size of an array.
template <typename T, std::size_t N>
constexpr std::size_t array_size(T (&) [N]) noexcept
{
return N;
}
But when is this useful?
template<typename T>
void foo(T& t)
{
// we now have a reference to bar
}
void bar() { }
int main()
{
foo(bar);
}
When do we care about preventing function to pointer decay? I'm asking about when this is useful, not why it isn't disallowed.
Like with objects, we us a pointer if “no object” (“no function”) is a sensible value and a reference if we wish to make sure that (unless somebody insists to shoot himself in the foot) there is always a valid object (function) referred to.
Consider the following poor man's function wrapper (wealthy man goes over there).
template<typename>
class Function; // never defined
template<typename ReturnT, typename... ArgT>
class Function<ReturnT(ArgT...)>
{
private:
ReturnT (*func_)(ArgT...);
public:
// Will also accept a 'nullptr'
Function(ReturnT (*func)(ArgT...)) noexcept : func_ {func}
{
}
ReturnT
operator()(ArgT... args)
{
return this->func_(args...);
}
};
Now we can write the following program, which works just fine.
#include <iostream>
int
add(int a, int b)
{
return a + b;
}
int
main()
{
Function<int(int, int)> f {add}; // ok
std::cout << f(5, 7) << std::endl; // ok, prints 12
}
However, we can also write the following program, which doesn't work so nice.
int
main()
{
Function<int(int, int)> f {nullptr}; // compiles fine
std::cout << f(5, 7) << std::endl; // compiles fine, crashes at run-time
}
Instead, if we had replaced the (*func) with (&func) in the template's definition,
// Won't accept a 'nullptr'
Function(ReturnT (&func)(ArgT...)) noexcept : func_ {func}
{
}
the line
Function<int(int, int)> f {nullptr}; // compile-time error
would have triggered a compile-time error.
To me the difference is like between normal variable reference and a pointer. References are nicer to deal with than pointers.
I had a use-case when I to customize a parts of an algorithm. It had some phases and I could switch between several options for each phase. This is of course achievable with pointers, but hey, you can use pointers instead of references pretty much everywhere too.
It looked similar to this:
#include <iostream>
using namespace std;
class Foo
{
public:
Foo(void(&t)()) : barish(t) { };
void fun() {barish();};
private:
void(&barish)();
};
void bar() { cout << "meow\n";}
void bark() { cout << "woof\n";}
int main()
{
Foo foo1(bar);
Foo foo2(bark);
foo1.fun();
foo2.fun();
}
You can customize fun and don't have to deal with dereferencing and asserts that it's not null.
I want to call all types of functions from a single table.
(Consider returns types are all void)
To illustrate what I am talking about, here is some code that obviously does not work.
#include <iostream>
#include <map>
#include <functional>
void foo(int x){std::cout<<x;}
void bar(){std::cout<<"bar";}
std::map<std::string, std::function<void()>> map =
{
{"foo", foo},
{"bar", bar}
};
int main()
{
map["foo"](2);
map["bar"]();
}
I am not opposed to a C style solution.
You could declare your pointer an old style C function pointer to
a variadic function like:
foo(...);
bar(...);
std::map<void(*)(...)> map =
{
{"foo", foo},
{"bar", bar}
};
but then foo and bar have to follow the variadic calling convention with va_args, va_start
etc and you may only pull C PODs from the list. Don't know if its worth the hassle. The calling method still somehow has to know which number of args to pass.
Looks a bit as if you may rethink your design.
If for example this is supposed to be a command table for a kind of CLI it might be better to pass an std::vector<std::string> to each potential command and make it figure out if the vector has the correct size() for its purpose.
If you totally forsake the type system, you can use boost::any as long as you get all the types exactly right everywhere. Right now only works with explicitly making everything a std::function but I'm sure there's a workaround for that too (update added an overload for free functions):
class Functions
{
public:
template <typename... T>
void add_function(const std::string& name, void (*f)(T...))
{
fs[name] = std::function<void(T...)>{f};
}
template <typename... T>
void add_function(const std::string& name, std::function<void(T...)> f)
{
fs[name] = f;
}
template <typename... T>
void call(const std::string& name, T... args)
{
auto it = fs.find(name);
if (it != fs.end()) {
auto f = boost::any_cast<std::function<void(T...)>>(&it->second);
if (f) {
(*f)(args...);
}
else {
std::cout << "invalid args for " << name << std::endl;
}
}
else {
std::cout << "not found: " << name << std::endl;
}
}
private:
std::map<std::string, boost::any> fs;
};
void baz() {
std::cout << "baz" << std::endl;
}
int main() {
std::function<void()> foo = []{ std::cout << "foo" << std::endl; };
std::function<void(int)> bar = [](int i){ std::cout << "bar(" << i << ")" << std::endl;
};
Functions f;
f.add_function("foo", foo );
f.add_function("bar", bar);
f.add_function("baz", baz);
f.call("foo");
f.call("bar", 42);
f.call("baz");
}
Functional, yes. Good idea? Note also that f.call("bar", 42u) will fail because you have to get every type exactly right.
I changed a bit your approach, and be aware it's just an example, I'm pretty sure it won't compile like this, but it will give you an idea of what I had in mind.
You can register your functions in an additional struct, and then call the appropriate one, forwarding the parameters.
struct Funcs
{
std::function<void(int)> _f1;
std::function<void()> _f2;
template<typename args...>
void call(std::string&& f_name, args...)
{
if(f_name == "foo")
_f1(std::forward(args)...)
if(f_name == "bar")
_f2(std::forward(args)...)
}
}
int main()
{
Funcs f;
f.call("foo", 2);
}
If you really want to store any function, and can always figure out how to call it correctly, you can expand on Oncaphillis' approach and just go ahead and cast the function pointers:
void foo(int);
float bar(double, struct baz);
std::map<void(*)()> map = {
{"foo", (void(*)())foo},
{"bar", (void(*)())bar}
};
Then you can cast them back when you use them:
//code to make sure that map["foo"] is of type `void(*)(int)`
(*(void(*)(int))map["foo"])(42);
//code to make sure that map["bar"] is of type `float(*)(double, struct baz)`
float result = (*(float(*)(double, struct baz))map["foo"])(3.14159, (struct baz){ /*whatever*/});
As you see, it is no problem to call any type of function that way, without restricting to variadic ones. However, this approach is very error prone as you completely do away with the safety provided by the type system, and your casts must be 100% correct. Weird stuff may happen if you don't. That's the same problem as with using boost::any.
I'm using a timer library in Arduino IDE that has a function which takes "void(*func)(void)" as a parameter and runs it after certain time.I need to pass a function in my code with that library, the problem is I need "n" functions that do the same thing (just the variables involved inside the function take different values, which I take from an array of struct), that's why I can't use only one function and I need to be able to compile different functions with identical syntax but different variables involved.
I don't know how I can resolve this, what I want to do is to be able to create functions like in a for loop,
for(int i=0;i<MAX_FUNC;i++)
{
void func[i](){
x= structuredata.x[i];
}
}
I know this syntax is completely wrong but I'd like to know how can I achieve something like this . I tried using classes instead, but the library didn't let me use void functions created in a class as parameters, it indicated "unresolved overloaded function type"
If you're into template overrides and can restructure your functions as such, a solution to packing up a stack of callbacks to be fired consecutively is closer than you may think. You can make this more generic if the consistency of the function is literally identical. I.e. you can do this instead:
#include <iostream>
int ar[5] = { 1,2,3,4,5 };
// your function here
template <int i>
void callback()
{
// your code here. i is provided
int x = ar[i];
std::cout << "Got Value: " << x << '\n';
};
////////////////////////////////////////////////////////////
// unraveller
template<int N>
void callback_set()
{
callback_set<N-1>();
callback<N-1>();
}
// base callback set
template<>
void callback_set<0>() {}
////////////////////////////////////////////////////////////
int main()
{
callback_set<3>();
return 0;
}
Output
Got Value: 1
Got Value: 2
Got Value: 3
You "register" callback_set<N> as your callback, and it will chain up the calls to your function(s) for you. If individualized access to different implementations is needed, you can still to that, using full specializations:
#include <iostream>
// prototypes
template <int i>
void callback() {};
// your functions here
template<>
void callback<0>()
{
std::cout << "Callback #0" << '\n';
}
template<>
void callback<1>()
{
std::cout << "Callback #1" << '\n';
}
template<>
void callback<2>()
{
std::cout << "Callback #2" << '\n';
}
////////////////////////////////////////////////////////////
// unraveller
template<int N>
void callback_set()
{
callback_set<N-1>();
callback<N-1>();
}
// base callback set
template<>
void callback_set<0>() {}
////////////////////////////////////////////////////////////
int main()
{
callback_set<3>();
return 0;
}
Output
Callback #0
Callback #1
Callback #2
In essence you style-up your registered callback using callback_set<N> where N is the number of callbacks you've provided overrides for. Just a thought, but seems like it would be a fairly elegant solution to your problem if I understand it correctly.
You need some metaprogramming for that...
const int MAX_FUNC = 1000;
typedef void (*Tcallback)();
struct Tdata
{
int whatever;
};
Tdata callbackData[MAX_FUNC];
Tcallback callbacks[MAX_FUNC];
template <int index>
void callbackToIndex()
{
// callback knows it's index and thus can access some global structure for it's data
printf("%u", index);
callbackData[index];
}
template <int index>
void callbackCreate()
{
callbacks[index] = &callbackToIndex<index>;
callbackCreate<index - 1>();
}
template <>
void callbackCreate<-1>()
{
}
void create()
{
callbackCreate<MAX_FUNC - 1>();
}
I would like to represent the following code using a UML diagram:
#include <iostream>
#include <boost/bind.hpp>
using namespace std;
class A {
public:
void bar() {std::cout << "A::bar()" << std::endl;}
};
// FUNC should be callable with arguments (int, A*)
template <typename FUNC>
class B {
public:
B(FUNC func, int data) : func_(func), data_(data){}
void operator()(A* ap){func_(data_, ap);}
FUNC func_;
int data_;
};
// object generator uses argument deduction to construct B
template <typename FUNC>
B<FUNC> makeB(FUNC func, int data) {
return B<FUNC>(func, data);
}
struct F {
static void apply(int a, int b, A* ap){
std::cout << "a+b = " << a + b << std::endl;
ap->bar();
}
};
int main() {
A* a = new A;
auto b = makeB(boost::bind(F::apply, 10, _1, _2), 20);
b(a);
}
Here is my first attempt. I think there is some room for improvement:
Should I capture pointers to F and A in the bind attributes or represent them serparately? Currently I'm showing both. I think the syntax for the F::apply attribute is also wrong.
What is the best way to write the signature template for the bind class?
Is there a better way to use decltype in B's template parameter? currently it looks a bit clumsy.
The purpose is to communicate how bind works to people who may not be familiar with it and perhaps convey a little about how bind works internally. The diagram should be as simple as possible so any hacks that are intuitive and not misleading are okay, it doesn't have to conform precisely to the UML standard.
update: This version fixes the type of bind's internal function pointer.
What's wrong with the code below? Latest version of g++ and clang both give error. I am sure I am missing something basic here.
#include <iostream>
struct Z
{
static const int mysize = 10;
};
Z f2();
int main()
{
std::cout << f2()::mysize << std::endl;
}
The motivation here is to be able to find out the size of an array using templates using code such as below. I know there are many ways, but just stumbled upon this idea.
template<int N> struct S
{
enum { mysize = N };
};
template<class T, int N> S<N> f(T (&)[N]);
int main()
{
char buf[10];
std::cout << f(buf)::mysize << std::endl;
}
f2() returns a value, not a type. You'd need to use the . operator on the return value instead of ::
The :: operator requires a type to be named on the lefthand side, while . allows for a value to be named. Your expression f2() does not name a type so it cannot be used in conjunction with ::.
As a side note, with a little more detail in the question we might be able to solve your real problem.
Your program contains two mistakes:
You are using the :: operator to access the member of an object. Use operator . ("dot") instead;
You declare function f2() and invoke it without defining it (this will give you a linker error).
Also, since static member variables are shared among all instances of a class (Z in this case), you do not need an object to access it;
Here is how you could fix your program:
#include <iostream>
struct Z
{
static const int mysize = 10;
};
Z f2() { return Z(); }
int main()
{
// Don't need an object to access a static variable...
std::cout << Z::mysize << std::endl;
// ...but if you really want to, do it this way...
std::cout << f2().mysize << std::endl;
}
Why don't you use this way to find out the size of array by templates:
#include <iostream>
template<int N> struct S
{
enum { mysize = N };
};
template<class T, int N> int f1(T (&)[N])
{
return N;
}
int main()
{
char buf[10];
std::cout << f1(buf) << std::endl;
}
And this one is closer to your variant:
template<class T, int N> S<N> f(T (&)[N])
{
S<N> foo;
return foo;
}
int main()
{
char buf[10];
std::cout << f(buf).mysize << std::endl;
}
Anyway, you will need to return an object from f and access it's member by ., not by ::.
But it's more probable that second variant will be slower, because first variant is fully compile-time, but in the second variant compiler may miss the optimization and don't optimize out the run-time creation of foo.
I think you need to add const int Z::mysize; after class declaration.