I have a template function which accepts a function-object ('functor') as a template parameter:
template <typename Func> int f (void) {
Func func;
return func ();
};
struct Functor {
virtual int operator () (void) = 0;
};
struct Functor0 : Functor {
int operator () (void) {
return 0;
}
};
struct Functor1 : Functor {
int operator () (void) {
return 1;
}
};
I want to avoid an if-else block like:
int a;
if (someCondition) {
a = f<Functor0> ();
}
else {
a = f<Functor1> ();
}
Is there a way to use something similar to dynamic binding, i.e something like:
a = f<Functor> (); // I know this line won't compile, it is just an example of what I need
and decide in runtime what (derived) type is passed as the template parameter?
Is there a way to use something similar to dynamic binding
No. This is fundamentally impossible. At some point in your code you need to have the case distinction. Of course, that doesn’t have to be written manually; you can use macros (or again templates) to generate the necessary code. But it needs to be there.
One way to avoid the check (if that is REALLY what you want to do), is to use an array - ..
Functor* fp[] = { new Functor0(), new Functor1() };
now - use someCondition as an index.
a = (*fp[someCondition])();
this relies simply on run-time polymorphism rather than the redundant template mechanism you are using... (btw. don't forget to cleanup!)
Of course, this is nasty and frankly redundant, the overhead of the if will be insignificant, but the clarity it adds to the code is significant...
Related
To start, I have something like this:
class Test {
std::vector<int> a, b;
void caller(...) { callee(...); }
void callee(...) { /* Do stuff with 'a' */ }
}
What I wanted is to have a function that does exactly the same as callee but for vector b. To do this there are two obvious solutions:
Pass vector a or b as argument. However, callee is a recursive function that can go for hundreds of calls, and passing the vectors as arguments would just be unnecessary overhead.
Copy the function callee and use vector b, which would be the best alternative, despite the fact that callee is quite a long function and I would have a lot of duplicate code.
Out of curiosity, I went looking for the templates part and I noticed that can be used for
lvalue reference type
pointer type
pointer to member type
So I tried to do this:
class Test {
std::vector<int> a, b;
void caller(...) { callee<a>(...); }
template <std::vector<int> &x> void callee(...) { /* Do stuff with 'x' */ }
}
but I get
error: use of ‘this’ in a constant expression
Is there any way to achieve this either with a reference or a pointer?
By the way, what I want can be seen as a function-scoped #define
Arrays and even tuples, but no love for good old pointers-to-members ?
class Test {
std::vector<int> a, b;
void caller(/*...*/) { callee<&Test::a>(/*...*/); }
template <std::vector<int> Test::*vec>
void callee(/*...*/) { /* Do stuff with `(this->*vec)` */ }
};
You cannot use a reference to a data member as a template argument: templates are compile-time, and the value of this is not known until runtime. In other words, you'd need a separate instantiation (separate binary code) for each runtime object of type Test.
What you can do is replace a and b with an array, and templatise callee by index into this array:
class Test {
std::array<std::vector<int>, 2> ab;
void caller(...) { callee<0>(...); }
template <size_t idx>
void callee(...) { /* Do stuff with 'ab[idx]' */ }
}
This way, you get only two instantiations of callee (one for 0 and one for 1), with the indexing done (or at least doable) at compile time.
Simply use a facade:
class Test {
std::vector<int> a, b;
void caller_a(...) { callee(a); }
void caller_b(...) { callee(b); }
void callee(std::vector<int> &a_or_b, ...) {
}
}
callee() will refer to its parameter, which will be passed in as one or the other class member.
In the same logic as #Angew's answer, you could also use std::tuple, and it's quite interesting as with tuple you can also use different kind of containers in your callee function :
class Test {
std::tuple<std::vector<int>, std::list<int> > ab;
void caller(...) { callee<0>(...); }
template <size_t idx>
void callee(...) {
...
auto aIt = std::get<idx>(ab).begin(); // gets either the vector or the list depending on template value
...
}
}
Let's suppose I have the following function interface:
void giveme(void (*p)());
That function simply accepts a pointer to a function with no return type and argument.
I'm wondering if exists a way (without change the interface) to pass a class method as parameter of that function.
I'll try to explain better with an example. I have a class, like:
class Foo {
public:
template<typename T>
void bar();
};
I want to pass bar<T> (of an addressable instance of the class) as parameter of the function giveme.
I thought to bind the method with an object, and obtain the function target.
Something like:
int main(int argc, char *argv[]) {
Foo foo;
std::function<void()> f = std::bind(&Foo::bar<int>, &foo);
giveme(f.target<void()>());
return 0;
}
It compiles, but obviously does not work because, from here:
TargetType shall match the target type, so that typeid(TargetType)==target_type(). Otherwise, the function always returns a null pointer.
So, if exists, what is a way to achieve it?
Here's one (very bad) idea:
Foo * foo_ptr; // maybe thread_local
void foo_call()
{
foo_ptr->bar<int>();
}
int main()
{
Foo foo;
foo_ptr = &foo;
give_me(&foo_call);
}
It's not pretty, but neither is your situation.
There's only one way I know of, and it's a terrible idea, and don't do this.
typedef void (*void_fn)();
struct stateful_void_fn_data = {
void_fn raw;
std::function<void()> actual;
std::atomic_bool in_use;
}
// a global array to hold your function bindings and such
extern stateful_void_fn_data stateful_functions[5];
// N stateless functions that defer to the correct global state
template<int n> void void_fn_impl() {stateful_functions[n].actual();}
extern stateful_void_fn_data stateful_functions[5] =
{{void_fn_impl<0>}, {void_fn_impl<1>}, {void_fn_impl<2>}, {void_fn_impl<3>}, {void_fn_impl<4>}};
// function to register a stateful and get a stateless back
void_fn allocate_void_fn(std::function<void()>&& f) {
for(int i=0; i<5; i++) {
if(stateful_functions[i].in_use.compare_exchange_weak(false, true)) {
stateful_functions[i].actual = std::move(f);
return stateful_functions[i].raw;
}
}
throw std::runtime_error("ran out of stateful functions :(");
}
// function to unregister
void free_void_fn(void_fn f) {
if (f == nullptr) return;
for(int i=0; i<5; i++) {
if (stateful_functions[i].raw == f) {
stateful_functions[i].in_use = false;
return;
}
}
throw std::runtime_error("unknown void function");
}
Basically, I generate 5 void() functions (void_fn_impl<N>), and each calls a function stored in one of the five a global array slots (stateful_functions[i].actual). Then, allocate_void_fn will store any std::function<void()> in the global array, and hand you the void() that calls that entry in the array. This function itself is stateless, because we've stored all the state in the global array. free_void_fn and in_use exist solely to make the functions reusable.
And of course, because RAII is good:
class hidden_state_void_fn {
void_fn raw;
public:
hidden_state_void_fn(std::function<void()>&& f)
:raw(allocate_void_fn(std::move(f)) {}
hidden_state_void_fn(const hidden_state_void_fn&& r) {
raw = r.raw;
r.raw = nullptr;
}
hidden_state_void_fn& operator=(const hidden_state_void_fn&& r) {
free_void_fn(raw);
raw = r.raw;
r.raw = nullptr;
}
~hidden_state_void_fn() {free_void_fn(raw);}
operator void_fn() {return raw;}
operator()() {raw();}
};
std::map<int,std::function<void()>> tasks;
template<int n>
struct task_wrapper{
static void f(){ if (tasks.count(n)) tasks[n](); }
task_wrapper(std::function<void()> fin){ tasks[n]=fin; }
~task_wrapper(){ tasks.erase(n); }
static std::shared_ptr< void(*)() > make(std::function<void()> fin){
auto self=std::make_shared<task_wrapper>(fin);
return { &f, fin };
}
};
A task_wrapper<N>::make(func) return a shared pointer to a stateless function pointer that will call the stateful func.
We can use the the usual techniques to create an array of K function pointers of signature shared_ptr<void(*)()>(*)(). Then we can have a shared_ptr<void(*)()> register_func( std::function<void()> ).
To find blanks, we can either do a linear search, or we could build a table of blanks. This could look like a traditional allocation/free "heap", or a range-tree of blanks, or whatever.
Another approach would be to literally create and save a DLL on the fly then load it and call the symbol. This could be done via hacks (have such a DLL and a known offset to modify, copy and write, then load and run) or by shipping a C++ compiler (or other compiler) with your code (!).
Ok so I'm trying to setup a template method that returns a reference of an undetermined type based on a parameter request. Everything looks fine but it keeps telling me that no overloaded method of the provided template method exists when I call it. The code looks something like this:
class IObj {
public:
int id;
}
class ObjOne : public IObj {}
class ObjTwo : public IObj {}
class ObjThree : public IObj {}
enum ObjectTypes {
O1Type,
O2Type,
O3Type
}
class ObjManager {
public:
std::vector< std::unique_ptr<ObjOne> > O1Holder;
std::vector< std::unique_ptr<ObjTwo> > O2Holder;
std::vector< std::unique_ptr<ObjThree> > O3Holder;
ObjManager() {}
template <class T>
T& GetObject(int oID, ObjectTypes oType) {
if(oType == ObjectTypes::O1Type) {
for(int i = 0; i < O1Holder.size(); i++) {
if(O1Holder[i]->id == oID) {
return *O1Holder[i];
}
}
}
else if(oType == ObjectTypes::O2Type) {
for(int i = 0; i < O2Holder.size(); i++) {
if(O2Holder[i]->id == oID) {
return *O2Holder[i];
}
}
}
else if(oType == ObjectTypes::O3Type) {
for(int i = 0; i < O3Holder.size(); i++) {
if(O3Holder[i]->id == oID) {
return *O3Holder[i];
}
}
}
}
}
int main() {
std::unique_ptr<ObjManager> oManager(new ObjManager());
ObjOne& a = oManager->GetObject(0, ObjectTypes::O1Type);
return 0;
}
Everything works fine, and I can make a method that returns a reference to the object stored in the vectors if I return their specific type, but I'm trying to reduce the redundancy of making many functions to return each different type. So I wanted to make a templated method that would return an object type based on which ever type I requested.
It's not giving me any errors it just keeps underlining the -> in the expression oManager->GetObject, and tells me there is no overloaded method for the template method call. Specifically it states "no instance of function template 'ObjManager::GetObject' matches the argument list, argument types are (int, ObjectTypes)" even though I'm passing an integer and ObjectTypes:: into the function's parameter list. I've looked all over for an answer to this but have not been able to find a similar situation to draw experience on.
EDIT: Sorry should have specified that this is a precursor to a vast list of vectors, I just put 3 of them for simplicity. That's why I'm trying to make a single function that can handle the return of different types so that I don't have to make a return function for every vector I create. And the purpose of returning a reference to the specified type is because each derived type will have unique data that is not in the base class, so I'm pulling the objects for editing.
As #tobi303 commented, you should definetly use the template Parameter T in your GetObject class. Then you would actually avoid repeating yourself as the Compiler will generate the code for you that you have repeated 3 times
template <class T>
T& GetObject(int oID) {
for(int i = 0; i < OHolder<T>.size(); i++) {
if(OHolder<T>[i]->id == oID) {
return *OHolder<T>[i];
}
}
While you would have to define a OHolder Template function, too.
It is not possible to change the return type of a function based on runtime information (such as your parameters), because they are obviously unknown to the compiler.
If you will always know at compile time which object type you are going to choose, you can use a trick:
Step 1: Turn your enum into a couple of empty structs:
struct O1Type {};
struct O2Type {};
struct O3Type {};
Step 2: Instead of using else ifs, use function overloading:
ObjOne& GetObject(int oID, O1Type) {/* TODO*/}
ObjTwo& GetObject(int oID, O2Type) {/* TODO*/}
ObjThree& GetObject(int oID, O3Type) {/* TODO*/}
You can now use
ObjOne& a = oManager->GetObject(0, O1Type());
(or, even better auto& a = oManager->GetObject(0, O1Type());)
You seem to be trying to use both run-time polymorphism AND the compile-time (template) polymorphism. It doesn't work this way. You cannot return multiple types from the SAME METHOD.
What you probably want to do is to either define a method like #yussuf described, or to fully start using run-time polymorphism - in which case you don't need three containers, and the type becomes part of the object ID.
I concur with #yussuf's approach. Just do that, it probably will solve your problem.
I would also recommend to use a hash / map instead of performing linear search, but this is a different story...
Root cause
Template argument type deduction can't be solely based on the return type of the function.
On the way to a solution
You could therefore add a dummy function argument to transfer the type information:
template <class T>
T& GetObject(int oID, ObjectTypes oType, T&x) {
...
}
and in main():
ObjOne& a = oManager->GetObject(0, ObjectTypes::O1Type, a);
Then the template type can be deduced.
But this will not solve your problem. This type deduction is at compile time, so that all the possible returns of the function should return the same type (or something that can be converted to it).
This is not the case of your code, which will lead to other compilation errors (see online failure).
The solution
The only workable solution is that you determine the common denominator to return. Make the function a non-template function returning an IObj&:
IObj& GetObject(int oID, ObjectTypes oType) {
...
}
You should then manage the return object as a polymorphic obhect as well. As the return is by reference, this is fine (i.e. no slicing occurs). The returned reference will really refer to the object returned, whatever its derived type could be. But you'd have to redesign your calling code for polymorphism:
IObj& a = oManager->GetObject(0, ObjectTypes::O1Type);
Online demo
But this is somewhat clumsy because you indicate in an enum the expected type, but then end with a reference to a parent that you can't handle so easily.
Conclusion
As you indicate in the function the expected return type, you'd better go for the solution in Yussuf's rexcellent answer, but applying the technique of the dummy argument for type deduction.
Ok so after much research, I have determined the best way to accomplish this is to create a custom container class like so:
#include <vector>
#include <memory>
class Base {
public:
int ID;
Base(int id) { ID = id; }
}
class A : public Base {
public:
int X;
A(int id) : Base(id) {}
}
class B : public Base {
public:
int Y;
B(int id) : Base(id) {}
}
template <class T>
class MyContainer {
private:
std::vector<std::unique_ptr<T>> internalContainer;
public:
MyContainer() {}
~MyContainer() {}
void CreateItem(int id) {
std::unique_ptr<T> newItem(new T(id));
internalContainer.push_back(std::move(newItem));
}
T& GetItem(int id) {
for(std::vector<std::unique_ptr<T>>::iterator it = internalContainer.begin(); it!= internalContainer.end(); ++it) {
if((*it)->ID == id) {
return **it;
}
}
}
}
int main() {
MyContainer<A> AList;
MyContainer<B> BList;
AList.CreateItem(0);
BList.CreateItem(0);
A& AOne = AList.GetItem(0);
B& BOne = BList.GetItem(0);
AOne.X = 10;
BOne.Y = 20;
std::cout << std::to_string(AOne.X) << "\n";
std::cout << std::to_string(BOne.Y) << "\n";
}
Let me know your opinions on if this is acceptable or if it can be improved! :)
I have a class which has a template:
template<class T = int> class slider;
The class has a void Process(void) method, so, I think it should be callable regarless of the type, return value is void and there are no parameters to it.
As for now I have this code to call process each frame in my application:
//class menu:
typedef boost::variant<std::shared_ptr<slider<int>>,std::shared_ptr<slider<float>>,std::shared_ptr<slider<double>>,std::shared_ptr<slider<char>>> slider_type;
std::map<std::string,slider_type> Sliders;
//buttons ... etc ...
void Process()
{
if(!Sliders.empty())
{
for(auto i = Sliders.begin(); i != Sliders.end(); ++i)
{
switch(i->second.which())
{
case 0://slider<int>
{
boost::get<std::shared_ptr<slider<int>>>(i->second)->Process();
break;
}
case 1://slider<float>
{
boost::get<std::shared_ptr<slider<float>>>(i->second)->Process();
break;
}
//.....
}
}
}
}
Is it possible to execute the functions Process() like in the following example?
for(auto i = Sliders.begin(); i != Sliders.end(); ++i)
{
switch(i->second.which())
{
boost::get<???Any???>(i->second)->Process();
}
}
If yes, how?
What would such a function return? You can't change the type of a function at runtime. And the point of a variant is that it's contents are determined at runtime.
The only thing it could return is a boost::any. Which is really just exchanging one kind of unknown for another (an unknown that's a lot harder to deal with when you don't know what it contains, mind you). But if you want to see such a visitor:
struct convert_to_any : public boost::static_visitor<boost::any>
{
template<typename T> boost::any operator() (const T& t) {return t;}
};
Use apply_visitor on that, and you will get an any back. Though I fail to see how that's helpful.
In any case, if you're using get on a variant, you are almost certainly doing the wrong thing. The correct way to access the elements of a variant is with a visitor, not with get.
In your case, the visitor should be simple:
struct ProcessVisitor : public boost::static_visitor<>
{
template<typename T> void operator() (const T& t) const {t->Process();}
};
Just use apply_visitor on that. If the variant contains a type that can be used with operator-> and the return value of that function can have Process called on it, then it will.
(Untested code!)
struct CallProcess : static_visitor<>
{
template <class T>
void operator()(const T &t) const
{
t->Process();
}
};
for(auto i = Sliders.begin(); i != Sliders.end(); ++i)
{
boost::apply_visitor(CallProcess(), i->second);
}
No, not at all. You have to visit and deal with the case of every type. That is much better done with a visitor than your switch hack.
It's not possible because boost::variant has no way to know that all the types in the variant have anything in common. In fact, since the compiler generates a distinct class for each template specialization used, the address of the Process() function that would need to be used is different for each type in the boost::variant. To get around this you could abandon variant and use virtual functions and polymorphic classes sharing a common base class.
Has anyone ever used pointers/references/pointer-to-member (non-type) template parameters?
I'm not aware of any (sane/real-world) scenario in which that C++ feature should be used as a best-practice.
Demonstation of the feature (for pointers):
template <int* Pointer> struct SomeStruct {};
int someGlobal = 5;
SomeStruct<&someGlobal> someStruct; // legal c++ code, what's the use?
Any enlightenment will be much appreciated!
Pointer-to-function:
Pointer-to-member-function and pointer-to-function non-type parameters are really useful for some delegates. It allows you to make really fast delegates.
Ex:
#include <iostream>
struct CallIntDelegate
{
virtual void operator()(int i) const = 0;
};
template<typename O, void (O::*func)(int)>
struct IntCaller : public CallIntDelegate
{
IntCaller(O* obj) : object(obj) {}
void operator()(int i) const
{
// This line can easily optimized by the compiler
// in object->func(i) (= normal function call, not pointer-to-member call)
// Pointer-to-member calls are slower than regular function calls
(object->*func)(i);
}
private:
O* object;
};
void set(const CallIntDelegate& setValue)
{
setValue(42);
}
class test
{
public:
void printAnswer(int i)
{
std::cout << "The answer is " << 2 * i << "\n";
}
};
int main()
{
test obj;
set(IntCaller<test,&test::printAnswer>(&obj));
}
Live example here.
Pointer-to-data:
You can use such non-type parameters to extend the visibility of a variable.
For example, if you were coding a reflexion library (which might very useful for scripting), using a macro to let the user declare his classes for the library, you might want to store all data in a complex structure (which may change over time), and want some handle to use it.
Example:
#include <iostream>
#include <memory>
struct complex_struct
{
void (*doSmth)();
};
struct complex_struct_handle
{
// functions
virtual void doSmth() = 0;
};
template<complex_struct* S>
struct csh_imp : public complex_struct_handle
{
// implement function using S
void doSmth()
{
// Optimization: simple pointer-to-member call,
// instead of:
// retrieve pointer-to-member, then call it.
// And I think it can even be more optimized by the compiler.
S->doSmth();
}
};
class test
{
public:
/* This function is generated by some macros
The static variable is not made at class scope
because the initialization of static class variables
have to be done at namespace scope.
IE:
class blah
{
SOME_MACRO(params)
};
instead of:
class blah
{
SOME_MACRO1(params)
};
SOME_MACRO2(blah,other_params);
The pointer-to-data template parameter allows the variable
to be used outside of the function.
*/
std::auto_ptr<complex_struct_handle> getHandle() const
{
static complex_struct myStruct = { &test::print };
return std::auto_ptr<complex_struct_handle>(new csh_imp<&myStruct>());
}
static void print()
{
std::cout << "print 42!\n";
}
};
int main()
{
test obj;
obj.getHandle()->doSmth();
}
Sorry for the auto_ptr, shared_ptr is available neither on Codepad nor Ideone.
Live example.
The case for a pointer to member is substantially different from pointers to data or references.
Pointer to members as template parameters can be useful if you want to specify a member function to call (or a data member to access) but you don't want to put the objects in a specific hierarchy (otherwise a virtual method is normally enough).
For example:
#include <stdio.h>
struct Button
{
virtual ~Button() {}
virtual void click() = 0;
};
template<class Receiver, void (Receiver::*action)()>
struct GuiButton : Button
{
Receiver *receiver;
GuiButton(Receiver *receiver) : receiver(receiver) { }
void click() { (receiver->*action)(); }
};
// Note that Foo knows nothing about the gui library
struct Foo
{
void Action1() { puts("Action 1\n"); }
};
int main()
{
Foo foo;
Button *btn = new GuiButton<Foo, &Foo::Action1>(&foo);
btn->click();
return 0;
}
Pointers or references to global objects can be useful if you don't want to pay an extra runtime price for the access because the template instantiation will access the specified object using a constant (load-time resolved) address and not an indirect access like it would happen using a regular pointer or reference.
The price to pay is however a new template instantiation for each object and indeed it's hard to think to a real world case in which this could be useful.
The Performance TR has a few example where non-type templates are used to abstract how the hardware is accessed (the hardware stuff starts at page 90; uses of pointers as template arguments are, e.g., on page 113). For example, memory mapped I/O registered would use a fixed pointer to the hardware area. Although I haven't ever used it myself (I only showed Jan Kristofferson how to do it) I'm pretty sure that it is used for development of some embedded devices.
It is common to use pointer template arguments to leverage SFINAE. This is especially useful if you have two similar overloads which you couldn't use std::enable_if default arguments for, as they would cause a redefinition error.
This code would cause a redefinition error:
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
void foo (T x)
{
cout << "integral";
}
template <typename T, typename = std::enable_if_t<std::is_floating_point<T>::value>>
void foo (T x)
{
cout << "floating";
}
But this code, which utilises the fact that valid std::enable_if_t constructs collapse to void by default, is fine:
// This will become void* = nullptr
template <typename T, std::enable_if_t<std::is_integral<T>::value>* = nullptr>
void foo (T x)
{
cout << "integral";
}
template <typename T, std::enable_if_t<std::is_floating_point<T>::value>* = nullptr>
void foo (T x)
{
cout << "floating";
}
Occasionally you need to supply a callback function having a particular signature as a function pointer (e.g. void (*)(int)), but the function you want to supply takes different (though compatible) parameters (e.g. double my_callback(double x)), so you can't pass its address directly. In addition, you might want to do some work before and after calling the function.
It's easy enough to write a class template that tucks away the function pointer and then calls it from inside its operator()() or some other member function, but this doesn't provide a way to extract a regular function pointer, since the entity being called still requires the this pointer to find the callback function.
You can solve this problem in an elegant and typesafe way by building an adaptor that, given an input function, produces a customised static member function (which, like a regular function and unlike a non-static member function, can have its address taken and used for a function pointer). A function-pointer template parameter is needed to embed knowledge of the callback function into the static member function. The technique is demonstrated here.