So, I'm editing my wrapper around an OpenGL Shader Program. I'm trying to modify it to use templates for the functions to set uniforms, as they are all almost the same.
My desired end result is for the call:
aProgram.set_Fglm("uformName", glm::vec3(0, 1, 2));
To call the template function:
template<class T, void (*F)(GLint, GLsizei, const GLfloat*)>
void Shader::set_Fglm(const string& _name, const T& _value) {
// do stuff using F()
}
with the template parameters <glm::vec3, gl::Uniform2fv>. Currently, I have in my cpp file the code:
template void Shader::set_Fglm<glm::vec3, gl::Uniform3fv>
(const string& _name, const glm::vec3& _value);
However, what currently happens is that I get a compile time error, saying that the Template parameter F can not be deduced. So, what I think I need is a way to say that, when we receive a parameter of type glm::vec3, we always want to use the same gl function.
If possible, I also wouldn't mind if, for example, I needed to call something like aProgram.set_F3glm. But if that's the case, how would I still have the implementation itself written only once. What I had before just stored an enum with each uniform that would then be checked to see what function to call, and the set function would just always take a c pointer.
Sorry if this is worded pretty terribly, but I'm not really sure what I'm doing.
You may write a traits for that, something like:
template <typename T> struct DefaultF;
// Specialization
template <>
struct DefaultF<glm::vec3>
{
static constexpr void (*Func)(GLint, GLsizei, const GLfloat*) = &gl::Uniform2fv;
};
template<class T, void (*F)(GLint, GLsizei, const GLfloat*) = DefaultF<T>::Func>
void Shader::set_Fglm(const string& _name, const T& _value) {
// do stuff using F()
}
Example
Note that you may remove template parameter F and use directly DefaultF<T>::Func in your function.
Related
I have encountered some strange behavior.
This code gives me errors:
struct Game {
void stop() {std::cout << "success\n";}
};
template<class ...Args>
struct holder {
std::map<std::string, std::function<void(Args...)>> funcMap;
template <typename T, typename U>
void connect(T* targObj, const std::string& funcName) {
std::function<void(Args...)> newFunc = std::bind(U, targObj);
//expected primary expression before ',' token on line above
funcMap[funcName] = newFunc;
}
void invoke(const std::string& funcName, class Args...Vals)
{funcMap[funcName](Vals...);}
};
int main() {
holder<> h;
Game g;
h.connect<Game, &Game::stop>(g, "close");
h.invoke();
}
It seems that std::bind does not like typenames as inputs. Is there a workaround for this? It works fine to manually use std::bind with the same parameters, but it is more boilerplate code:
std::function<void(Args...)> newFunc = std::bind(&ae::Game::stop, targObj);
Even without any input, it still errors on compile. Why doesn't my function work?
EDIT: Thanks for the help. As it turns out, bind does not accept a typename, it accepts an address.
I guess the function is static ?
If not you have the solution, it needs an object to be called.
But bind is trying to call g with argument "close"on no object, can t work if not static
It's pretty straightforward really:
template <typename T, typename U>
void connect(T* targObj, const std::string& funcName) {
T and U must be types, since they are type templates. This function is a little awkward that it forces one to write both template parameters.
h.connect<Game, &Game::stop>(g, "close");
T=Game, and Game is a type, so that's good. U=&Game::stop, which is a variable/instance of void (Game::*)(), so that's the cause of your failure. I don't know why your compiler is giving silly errors. The solution is to pass the function variable as a parameter:
template <typename T>
void connect(T* targObj, void(Game::func*)(Args...), const std::string& funcName)
and calling it as:
h.connect(g, &Game::stop, "close");
As shown here: http://coliru.stacked-crooked.com/a/895584175a1a6a61
For anyone trying to accomplish this:
Just use macros. This is close to impossible without a custom bind implementation.
#define BINDMF(a,b,c) (std::bind(&a::b, c))
I have this function:
template <typename T, void (T::*pf)()>
void call(T& t)
{
(t.*pf)();
}
If I have class foo with a method with the appropriate signature (say bar) I can call it like this call<foo, &foo::bar>(); and it's fine. However if bar is const gcc and msvc are happy to compile it when called like this call<const foo, &foo::bar>(). Clang complains that the second template parameter is invalid. When I put const in the template arguments (void (T::*pf)() const) all tree compile it.
Now, this is not a huge issue, but my code becomes much much cleaner if I don't have to write this wretched const in the template arguments.
So the question basically is: What does the standard say about this? Is this a clang bug or are gcc and msvc just letting it slide because they're cool like that?
PS Here's a link to a complete repro program: http://codepad.org/wDBdGvSN
The const-ness of a method is part of the 'signature' of it. So, the proper way to define and use a pointer to member is:
R (Obj::*)(Args) // for non-const member
R (Obj::*)(Args) const // for const member
Note that a const member can be called on a non-const object, which is not the case with R (const Obj::*)(Args).
A way to solve this is to abstract such function pointers, by defining 'call wrappers':
template<typename O, void (O::* f)()>
struct NonConstFunc
{
static void call(O* o)
{
(o->*f)();
}
};
template<typename O, void (O::* f)() const>
struct ConstFunc
{
static void call(O* o)
{
(o->*f)();
}
};
Then, you can use it the following way (here the abstraction takes place):
template<typename Obj, typename Function>
void call(Obj* o)
{
Function::call(o);
}
There is a live example here.
This is just the main idea. You can extend it with automatic detection of whether the method is const or not, without changing the user code.
I want to do something like the following:
Example(&Class::MemberFunction, this));
//...
template<class T_CLASS>
inline static void Example(void (T_CLASS::*MemberFunctionPointer)(), T_CLASS* InstancePointer)
{
SomeClass<T_CLASS>::Bind<MemberFunctionPointer>(InstancePointer);
}
But I get the error: *template parameter 'T_MEMBER_FUNCTION' : 'MemberFunctionPointer' : a local variable cannot be used as a non-type argument*
Any solutions for this problem? I want to provide an easier way to call "Bind"
Thanks, Mirco
//edit:
I want MemberFunctionPointer to be a non-type template parameter because in "Bind" I again need it as a template argument.
As you wrote in your answers, in my case MemberFunctionPointer is a variable and its value is unknown at compile time. But MemberFunctionPointer always points to the same function. Is there a way to for example make it constant so that the compiler knows it at compile time?
There are two kinds of things template parameters can be: types and compile-time constant expressions. The contents of a function parameter is not a compile-time determinable value. And therefore, the compiler cannot instantiate a template based on it.
Remember: a template is a type. And types must be determinable at compile time.
You probably should pass the member pointer as an argument to the Bind function.
I am not quite sure what you are trying to achieve?
If a MemberFunctionPointer is a variable, that the value of is unknown at compile time and, for example, may depend on some user behaviour - then it cannot be used as a template argument.
If, on the other hand, MemberFunctionPointer can be actually deduced at compile-time, you should pass it as a template argument, instead of a function parameter. Consider the following example:
(use Bind and call in the first case; in the second case, use StaticBind and callStatic)
#include <stdio.h>
class X {
public:
int x;
void foo() {printf("foo\n");}
void bar() {printf("bar\n");}
};
template <typename T>
class SomeClass {
public:
static void Bind(void (T::*MemberFunctionPointer)(), T *obj) {
(obj->*MemberFunctionPointer)();
}
template <void (T::*MemberFunctionPointer)()>
static void StaticBind(T *obj) {
(obj->*MemberFunctionPointer)();
}
};
template <class C>
static inline void call(void (C::*MemberFunctionPointer)(), C *obj) {
SomeClass<C>::Bind(MemberFunctionPointer,obj);
}
template <class C, void (C::*MemberFunctionPointer)()>
static inline void callStatic(C *obj) {
SomeClass<C>::template StaticBind<MemberFunctionPointer>(obj);
}
int main() {
X obj;
call<X>(&X::foo,&obj);
callStatic<X,&X::bar>(&obj);
return 0;
}
Template parameters have to be known at compile-time. The contents of a pointer variable that is a function's parameter depends on how this function is invoked. This is not known at compile-time!
If you know this pointer at compile-time already, you can turn the function pointer runtime parameter into a template parameter:
template<class T_CLASS, void(T_CLASS::*MemFunPtr)()>
void Example(T_CLASS* InstancePointer) {...}
Here, MemFunPtr is a template parameter that is known at compile-time and can thus be resused as a template parameter for another function or class template...
MemberFunctionPointer is a variable not a type (or compile-time constant), hence cannot be used, what you need is the real signature of that function, something like this may be better..
template<typename T_FUNC_PTR, class T_CLASS>
inline static void Example(T_FUNC_PTR fPtr, T_CLASS* InstancePointer)
{
SomeClass<T_CLASS>::Bind<T_FUNC_PTR>(fPtr, InstancePointer);
}
i.e. let the compiler deduce the type of the function pointer (NOTE: you will have to propagate the pointer to the function too), to call
Example(&foo::bar, foo_inst);
This is untested and off the top of my head, so the syntax could be slightly off...
EDIT: here is a simpler example to demonstrate the concept:
#include <iostream>
struct foo
{
void bar() { std::cout << "foo::bar()" << std::endl; }
};
template<typename T_FUNC_PTR, typename T_CLASS>
void exec(T_FUNC_PTR ptr, T_CLASS& inst)
{
(inst.*ptr)();
}
int main(void)
{
foo inst;
exec(&foo::bar, inst);
}
Suppose I have arbitrary template method, which could receive parameters by value and by const reference (obviously, for trivial types and for objects accordingly).
How is this situation handled when writing template function prototypes?
I could make something like:
template <typename T> void Foo(T value) {
// Do something.
}
template <typename T> void Foo(const T& value) {
// Do something, yeah.
}
// Specialization for first prototype.
template <> void Foo<int>(int value) { }
// Specialization for second prototype.
template <> void Foo<Object>(const Object& value) { }
But this approach is only okay for trivial functions, that act purely as a wrapper for some other calls.
If the function (non-templated version) has a lot of code inside it, this means I would have to copy the code twice.
Can I make something smarter here?
Just take by const reference ALWAYS, because there isn't much overhead in passing primitive types as const references.
Write your template code for const references only and rely on the compiler to optimize the references away.
I'm basically looking to generate a wrapper for a generic C function without having to manually specify the types. So I have a callback with a fixed prototype but I'm going to need to do some special code in the wrapper based on the type of the wrapped function... So basically I'm thinking about using a static method in a class template to wrap my function to a conforming interface e.g.:
// this is what we want the wrapped function to look like
typedef void (*callback)(int);
void foobar( float x ); // wrappee
// doesn't compile
template< T (*f)(S) > // non-type template param, it's a function ptr
struct Wrapper
{
static void wrapped(int x)
{
// do a bunch of other stuff here
f(static_cast<S>(x)); // call wrapped function, ignore result
}
}
And then I'd like to do something like:
AddCallback( Wrapper<foobar>::wrapped );
However, the problem is that I can't just go ahead and use a "S" in the parameter of the function in the Wrapper template, I have to first list it as a parameter:
template< class T, class S, T (*f)(S) >
struct Wrapper
// ...
But this means it's a lot more painful to use (Wrapper<void,float,foobar>::wrapped), ideally I'd like to just pass in the function pointer there and have it work out the types of the parameters (and return types) automatically. To be clear, inside the wrapped function I'm going to need to refer to the types of the function pointer (so I do need some equivalent of S or T).
Is there a way of doing this?
One thing you might wish to consider is using LLVM or similar to generate an appropriate trampoline function at runtime. Or here's a static solution:
#include <iostream>
void f(float f) { std::cout << f << std::endl; }
template<typename T, typename S> struct static_function_adapter {
template<T(*f)(S)> struct adapt_container {
static void callback(int v) {
f(static_cast<S>(v));
}
};
template<T(*f)(S)> adapt_container<f> adapt() const {
return adapt_container<f>();
}
};
template<typename T, typename S> struct static_function_adapter<T, S> get_adapter(T (*)(S)) {
return static_function_adapter<T, S>();
}
#define ADAPTED_FUNCTION(f) (&get_adapter(f).adapt<f>().callback)
int main() {
void (*adapted)(int) = ADAPTED_FUNCTION(f);
adapted(42);
return 0;
}
The get_adapter function allows us to infer the argument and return type; adapt() then converts this into a type parameterized on the actual function, and finally we get a static function in callback.
If you use a function that returns the "wrapped" rather than referring to it directly, the compiler will attempt to automatically match the template parameters for the function call.
edit: What about this?
int foobar( float x ); // wrappee
template <typename T, typename S>
struct Wrapper {
typedef T (*F)(S);
F f;
Wrapper(F f) : f(f) { }
void wrapped(S x) {
// do a bunch of other stuff here
f(x); // call wrapped function, ignore result
}
};
template <typename T, typename S>
Wrapper<T,S> getWrapper(T (*f)(S)) {
return Wrapper<T,S>(f);
}
...
getWrapper(foobar).wrapped(7);
EDIT: completely new answer
OK, I've completely re-thought the question and believe that I get what you want. I've actually done this before :-P.
Here's the idea, I have a Base class which overloads operator(), then I have a subclass for each "arity" of functions. Finally I have a factory function which will return one of these things. The code is big (and probably a little overkill) but works nicely. Much of the library_function overloads are to support different syntaxes, mostly unnecessary. It also supports boost::bind functions, member functions, etc, very much more than you probably need.
http://pastebin.com/m35af190
Example, usage:
// map of library functions which will return an int.
std::map<std::string, LibraryFunction<int> > functions;
// function to register stuff in the map
void registerFunction(const std::string &name, LibraryFunction<int> func) {
functions.insert(std::make_pair(name, func));
}
later you can do this:
// the this param is so the function has access to the scripting engine and can pop off the parameters, you can easily chop it out
// register 2 functions, one with no params, one with 1 param
registerFunction("my_function", library_function1(*this, call_my_function));
registerFunction("my_function2", library_function0(*this, call_my_function2));
functions["my_function"]();
functions["my_function2"]();
I'd look at boost. At first reading of your question, it seems to me than <boost/function_types/parameter_types.hpp> provides what your need.