Need clarification on C++ template format - c++

I'm going through some template sample code and there's one thing I don't get.
Take a template methode:
template<class Seq, class T, class R>
void apply(Seq &sq, R(T::*f)() const) {
typename Seq::iterator it = sq.begin();
while(sq.end() != it) {
((*it++)->*f)();
}
}
A sample class:
class MyClass {
public:
MyClass() {}
void doSomething() const {
std::cout << "doing stuff..." << std::endl;
}
};
And the test code:
void testMyClass() {
vector<MyClass*> v;
for(size_t i = 0; i < 5; ++i) {
v.push_back(new MyClass());
}
// call a member methode on all elements in container
apply(v, &MyClass::doSomething);
}
I would be grateful if someone could explain me what is that class R for, as defined in the template definition?

class R refers to the return type of the function pointer being passed to the function apply. It is automatically deduced from the actually passed function pointer type, so you never really need to care about it when calling apply.
The implementation of apply discards the return value of the function, so you could simply force the passed function to return void:
template<class Seq, class T>
void apply(Seq &sq, void(T::*f)() const) {
typename Seq::iterator it = sq.begin();
while(sq.end() != it) {
((*it++)->*f)();
}
}
However, now you restrict the call site to only pass such function pointers. Sadly, a pointer to a function which returns something isn't implcitly convertible to one which doesn't, although it would be pretty "intuitive".
So when you take a function pointer as an argument, and you don't care about the return type, it's better to accept "any" return type than "none".

class R in the template is used to deduce the return type of the function. In your case, it is deduced to be of type void.

Related

Passing a templated functor as an argument to a templated function in C++

I am trying to pass a templated functor into a templated function.
The code looks something like this:
template<typename T>
T func_1(T &a) {
return a;
}
template <typename T>
T test(T &a, std::function<T(T&)> &func){
return func(a);
}
int main(){
int a = 5;
std::cout << test(a, func_1) << std::endl;
}
However, I get the following compile error:
invalid initialization of non-const reference of type ‘std::function<int(int&)>&’ from an rvalue of type ‘’
The code works if I remove the template. Can someone help me understand why?
func_1 is function template. You have to pass a concrete type you want this function to be instantiated. In your case it is int, type of a variable.
std::cout << test(a, func_1<decltype(a)>) << std::endl;
Then, function object can be created taking func_1<int> instantiation. This function is temporary, but temporary cannot be bound to Lvalue reference, so signature of test should be modified to accept const Lvalue ref:
template <typename T>
T test(T &a, const std::function<T(T&)> &func){
// <---- const
return func(a);
}
The issue is that func_1 is just a template, to get a function pointer you first need a function (ie an instantiation of the function template).
You can get what you want by making func_1 an actual functor (ie callable object) that is not a template itself:
#include <functional>
#include <iostream>
struct func_1 {
template <typename T>
T operator()(T& a){ return a; }
};
template <typename T,typename F>
T test(T &a, F func){
return func(a);
}
int main(){
int a = 5;
std::cout << test(a, func_1{}) << std::endl;
// ^^ create instance
}
The "trick" is that only func_1::operator() is a template, so you can create objects of func_1 and pass them around before you know what T actually is. The operator is only instantiated when it is called in test but not in main.

How to call a class member function from 2 void pointers

So for this function:
template<typename T>
T popObject(ScriptObject obj) { //Preforms a cast from void* on each to its type.
assert(obj.getType() == std::type_index(typeid(T))); //Ensure type Safety.
return obj.get<T>();
}
template <typename C, typename...Args>
void bind(const char* name, C* context, void(C::* function)(Args...)) {
std::vector<std::type_index> arguments = { std::type_index(typeid(Args))... };
auto functor = [](void* func,void* contex, std::vector<ScriptObject> stack) {
std::size_t idx = 0;
//Call class context -> function (Args...)
};
_functions[name] = new BoundFunction(functor, void_cast(function), context, arguments);
}
I'm unsure of the syntax for calling the member function.
Iv tried:
union MF{
void(C::* pf)(Args...);
void* p;
} mf;
mf.p = func;
contex->*(mf.pf)(popObject<Args>(stack[idx++])...);
Which does not compile, Stating: "Does not evaluate to a function taking 1 Arguments."
Tried std::invoke, But I Don't know how to Specify the Member function Signature for arg1.
So If i have a reference to the member function, And a reference to the instance of the class, As well as the template information to Derive type information. How do I call the Classes member function?
Thanks #Igor Tandentnik
Final Solution was:
(static_cast<C*>(ctx)->*(mf.pf))(popObject<Args>(stack[idx++])...);
As Igor pointed out, it needed to be ->* instead of .*, and added parenthesis, as -> has a lower priority then the Function call operator.
Also, thanks #TheFloatingBrain for pointing out the extra static_cast

Specialize a template for void parameter

I have a the following template and specialization (this code is not correct, but hopefully demonstrates my intent well enough):
template <typename T> widget &&make_widget(T &&val) { // (1)
return std::move(widget(std::forward<T>(val)));
}
template <> widget &&make_widget(void) { // (2)
return std::move(widget());
}
The intent is to have a factory function that can be called like this:
make_widget(arbitrary_function());
And have it choose the default constructor if arbitrary_function returns void.
However, with clang 3.7 I get the following error:
error: no function template matches function template specialization 'make_widget'
pointing to the line of (2). How can I implement this correctly?
You can't do this. It's impossible to create a function that has a parameter of type void. What you can do is make the function variadic, like make_unique.
template <typename... T>
widget make_widget(T&&... val) {
return widget(std::forward<T>(val)...);
}
Then if you want to do something like
auto w = make_widget(void_function());
there is nothing stopping you from just doing instead:
void_function();
auto w = make_widget();
or even, if you really need it to be one statement for some reason,
auto w = (void_function(), make_widget());
Three further notes:
You should nix the std::move in the return statement since the result of calling the constructor is already an rvalue.
Never return a reference (even rvalue reference) to a temporary! It will always become a dangling reference.
There is no point to the make_widget function if forwarding its arguments to the widget constructor is the only thing it does. Note that make_unique takes care of calling new for you, and that make_tuple deduces the template arguments for the tuple itself. Your make_widget function doesn't do anything like that.
As it's been pointed out, the problem is not really in the template specialization, but the usage of a void expression.
I can, however, suggest an alternative syntax that uses an intermediate lambda, and a helper template, to achieve the same results at a cost of a little bit of negligible extra usage syntax.
#include <functional>
class widget {
public:
widget();
widget(int);
};
template <typename T> widget &&do_make_widget(T &&val) { // (1)
return std::move(widget(std::forward<T>(val)));
}
widget &&do_make_widget() { // (2)
return std::move(widget());
}
template <typename T>
class do_make_widget_invoke {
public:
template<typename functor_type>
static auto invoke(functor_type &&functor)
{
return do_make_widget(functor());
}
};
template <>
class do_make_widget_invoke<void> {
public:
template<typename functor_type>
static auto invoke(functor_type &&functor)
{
functor();
return do_make_widget();
}
};
template<typename functor_type>
auto make_widget(functor_type &&functor)
{
return do_make_widget_invoke<decltype(functor())>
::invoke(std::forward<functor_type>(functor));
}
Testing the above with g++ 5.1.1 in -std=c++14 mode, I seem to get the right results with the following syntax, which is pretty much what you're trying to accomplish:
int foobar()
{
return 0;
}
int main()
{
make_widget([]{ return foobar(); });
}
and:
void foobar()
{
}
int main()
{
make_widget([]{ return foobar(); });
}

How does wrapping a function pointer and function object work in generic code?

The following template definition
template <typename Func, typename ReturnType, typename... Arguments>
class Command
{
public:
Command(Func f) : m_func(f) { }
ReturnType operator()(Arguments... funcArgs) { return m_func(funcArgs...); }
private:
Func m_func;
};
gives an error message with gcc 4.7.3 (error: field 'Command::m_func' invalidly declared function type) when instantiated with the following test code:
void testFunction(int i, double d)
{
std::cout << "TestFunctor::operator()(" << i << ", " << d << ") called." << std::endl;
}
int main()
{
void (&fRef)(int, double) = TestFunction;
Command<void(int, double), void, int, double> testCommand(fRef);
}
The error message also occurs if I pass TestFunction without the address-of operator into the testCommand constructor, but disappears if I pass either an explicitly named function pointer or use the address-of operator to pass the parameter. I'm under the impression that this code should work given Chapter 5 of Modern C++ Design.
What is the reasoning behind not being able to store a reference to a function, but function pointers work fine? Are there any workarounds that would allow this to compile without losing support for being able to pass functors as arguments to Command's constructor as well?
Changing one line could fix it:
Command<void(*)(int, double), void, int, double> testCommand(fRef);
The difference is, you're passing a function pointer now, instead of a function type. (Functions aren't copyable, but pointers are).
The reference fRef decays to a function pointer when you pass it.
I wouldn't suggest using std::function if performance mattered.
See it live on Coliru
Note that with a little rewriting, you can make it all work much nicer:
int main()
{
auto command = make_command(testFunction);
command(1, 3.14);
}
To do this, I'd suggest changing the Command template to be:
template <typename Func>
class Command
{
Func m_func;
public:
Command(Func f) : m_func(f) { }
template <typename... A> auto operator()(A... args) const
-> decltype(m_func(args...))
{ return m_func(args...); }
};
And now you can have type-deduction on the Func template parameter by having a factory function:
template <typename Func> Command<Func> make_command(Func f)
{
return Command<Func>(f);
}
See this approach live on Coliru too. Of course, the output it the same:
TestFunctor::operator()(1, 3.14) called.
C++11 offers an std::function template. You don't have to mess with function pointers.
You can pass those by reference, copy them, move them and they can even be used to store lambdas:
std::function<void()> func = []() { std::cout << "Hi" << std::endl; };

Failure to Match Template Using Function Pointer as Argument

I am attempting to write a function which will operate on a std::map of any key and class pointer given to it, and create a new std::map with an index based on the return value of a function in the class. Essentially, a template function to re-index a map based on a function in its contained class. However, I am having compiler errors when trying to invoke the function.
template<class AnyType, class ValueType, class FunctionType>
AssocArray<FunctionType,ValueType> reindex( const AssocArray<AnyType, ValueType>& original, FunctionType (*getterFunction)() ) {
AssocArray<FunctionType, ValueType> ret;
FunctionType index;
for(typename AssocArray<AnyType,ValueType>::const_iterator it = original.begin(); it!=original.end(); it++) {
index = ((*it->second).*getterFunction)();
ret[index] = it->second;
}
return ret;
}
Invoked by:
floatIndexed = reindex( intIndexed, &test::getB );
Where getB is of float type.
This results in the compiler error:
src/World.cpp:78:50: error: no matching function for call to ‘reindex(std::map<int, onathacar::test*>&, float (onathacar::test::*)())’
src/World.cpp:78:50: note: candidate is:
./include/Types.h:123:36: note: template<class AnyType, class ValueType, class FunctionType> std::map<PreservedType, ValueType> onathacar::reindex(const std::map<LookupType, ValueType>&, FunctionType (*)())
I have tried different variations of this, including using "FunctionType (ValueType::*getterFunction)()" and changing "AssocArray" to "AssocArray". The only one which worked added a fourth template argument:
template<class AnyType, class ValueType, class FunctionType, class SomeType>
AssocArray<FunctionType,ValueType> reindex( const AssocArray<AnyType, ValueType>& original, FunctionType (SomeType::*getterFunction)() ) {
However, this seems like it would potentially allow functions that are not actually members of ValueType to be called, and so I would prefer some other option. I am not even sure what is wrong, as it appears the templates match, at least with the addition of "ValueType::". Why does the call not match the template, and is there a way to fix it without a fourth templated type?
For more context, Header Containing Implementation and Calling Function.
You have two problems. The first is that reindex implies that the value types are values, but you use them as pointers:
AssocArray<float, test*> floatIndexed;
floatIndexed = reindex( intIndexed, &test::getB );
The second is that reindex's second parameter needs to be declared as a member function, not a free function. So reindex should look like this:
template<class AnyType, class ValueType, class FunctionType>
AssocArray<FunctionType,ValueType *> reindex( const AssocArray<AnyType, ValueType *>& original, FunctionType (ValueType:: *getterFunction)() ) {
AssocArray<FunctionType, ValueType*> ret;
FunctionType index;
for(typename AssocArray<AnyType,ValueType*>::const_iterator it = original.begin(); it!=original.end(); it++) {
index = ((*it->second)->*getterFunction)();
ret[index] = it->second;
}
return ret;
}
It seems that you are trying to use your rindex() function with members but your function is declared to use non-members. This won't work. The reason this won't work is that the you need an object to access either function or data members of a class.
template<class A, class B>
class X{
public:
};
class Y{
public:
int func() { return 42; }
};
template<class A, class B, class C>
X<C,B> reindex( const X<A, B>& original, C (B::*getterFunction)() ) {
X<C, B> x2;
cout << "hello" << endl;
return x2;
}
int main() {
X x1;
reindex(x1,&Y::func);
return 0;
}
This works and gives perfectly valid results.
The problem with your call AssocArray intIndexed, is the fact that you are trying to pass &test::getB as the getter function, which assumes valueType = test, where as your actual value type, is test*.