C++ template overload call - c++

I am trying to implement an execution pattern which takes any function and executes it with its own conditions/preparations. Regardless of this being a useful thing to do, it just doesn't work. It seems i can't access the template overload of the "Execute"-function (called in "main").
Specifically: Why can't i call the overloaded template function of Execute?
This is the full program:
#include "stdafx.h"
#include <functional>
class TransparentFunctionWrapper
{
public:
virtual void Execute(std::function<void()> executeFunction) = 0;
template<class C>
C Execute(std::function<C(void)> executeFunction) // template-overload of the abstract function which will implicitly call it
{
C ret;
Execute( // calls the abstract function with a lambda function as parameter
[ret, executeFunction](void) -> C // lambda declaraction
{ //
ret = executeFunction; // lambda body
}); //
return ret;
}
};
class ExampleExecutor : public TransparentFunctionWrapper
{
public:
virtual void Execute(std::function<void()> executeFunction)
{
printf("executed before.");
executeFunction();
printf("executed after.");
}
};
void DoStuff() {}
int ReturnStuff() { return -5; }
int main()
{
ExampleExecutor executor;
executor.Execute(DoStuff);
int i = executor.Execute<int>(ReturnStuff); // Why does this not work? ERROR: "type name is not allowed"
getchar();
return 0;
}
Note: Visual Studio marks
Execute<int>(ReturnStuff) // "int" is marked as Error: type name is not allowed
The compilation puts out the error
"type 'int' unexpected"
Thanks to everyone willing to help!

ExampleExecutor::Execute is not overriding TransparentFunctionWrapper::Execute, and it is hiding it in the executor.Execute<int> call.
You must explicitly call TransparentFunctionWrapper::Execute, as it is hidden by ExampleExecutor::Execute. Here's a possible way of doing that:
int i = executor.TransparentFunctionWrapper::Execute<int>(ReturnStuff);
live example on coliru

Related

Why doesn't passing a function with default parameters to a templatized constructor and storing it using a lambda as std::function<void()> work?

Take this simplified example:
Command.h:
class Command {
public:
template<typename Func>
Command(Func newToExecute) : toExecute([&newToExecute](){newToExecute();}) { }
void callFunction(); //defined in Command.cpp -> calls function with toExecute();
private:
std::function<void()> toExecute;
};
Main.cpp:
void test(int var = 0) {
//does irrelevant things
}
int main() {
Command testCommand(test);
testCommand.callFunction();
return 0;
}
When trying to run this I get an error from the compiler using MinGW:
error: too few arguments to function Command(Func newToExecute) : toExecute([&newToExecute](){newToExecute();}) { }
Now I wouldn't have done all this just to save a simple void function, if this wasn't working:
//in the Command class:
Command(std::function<void()> newToExecute) : toExecute(std::move(newToExecute)) { } //rest unchanged
//in the main function:
Command testCommand([](){test();}); //rest unchanged
Coming from the last code example I see no reason, why the first one shouldn't work. Would anyone please explain why it is not working?
Edit: Missed a small detail in the working version, but still not closer to the explanation.
Your second version doesn't take the address of test. The type of that &test is void (*)(int), not void (*)().
This is also why you can't construct a std::function<void()> from test directly.

std::async with non static member functions

I am trying to evaluate a part of my code asynchronously
#include <stdio.h>
#include <string>
#include <memory>
#include <future>
#include <map>
namespace IG
{
typedef std::map<uint, std::string> CadDef;
class FooFoo
{
CadDef foo()
{
CadDef cdef{};
cdef[1] = "aa";
return cdef;
}
};
}
int main()
{
auto ptr = std::make_unique<IG::FooFoo>();
std::future<IG::CadDef> resFut = std::async(ptr->foo);
auto res = resFut.get();
return 0;
}
But the code doesn't compile -
(On gcc)
error: invalid use of non-static member function ‘IG::CadDef IG::FooFoo::foo()’
(on msvc -- my main program, from where I abstracted the minimal example)
error C3867: 'IG::FooFoo::foo': non-standard syntax; use '&' to create a pointer to member
error C2672: 'std::async': no matching overloaded function found
error C2780: 'std::future<_Invoke_traits<void,decay<_Ty>::type,decay<_ArgTypes>::type...>::type> std::async(std::launch,_Fty &&,_ArgTypes &&...)': expects 3 arguments - 1 provided
Seems like MSVC is complaining that I have not used ptr->foo() but I am not sure.
What am I doing wrong?
You can use a lambda like following, using a policy*
auto handle = std::async(std::launch::async, [&ptr](){
return ptr->foo(); // Ofcourse make foo public in your snippet
});
auto res = handle.get();
*Not necessarily required
Async takes a function address as an argument, but it the function is a class-member function you have to bind it to the object which can invoke this function.
All functions (including methods) are moved to the code segment of the binary file.
That's why the sizeof(T) equals to sum of sizeof of all class data-members (including a virtual table pointer (vptr) if exists).
class A {void method() }; can be represented as void method(A* a) {}
Knowing all this information you should bind the method with the object
int main()
{
auto ptr = std::make_unique<IG::FooFoo>();
std::future<IG::CadDef> resFut = std::async(&IG::FooFoo::foo, ptr.get());
auto res = resFut.get();
return 0;
}

Call of overloaded function is ambiguous although different namespace

I do understand why the following would be a problem if no namespaces were used. The call would be ambiguous indeed. I thought "using stD::swap;" would define which method to use.
Why does it work for "int" but not a "class"?
#include <memory>
namespace TEST {
class Dummy{};
void swap(Dummy a){};
void sw(int x){};
}
namespace stD {
void swap(TEST::Dummy a){};
void sw(int x){};
class aClass{
public:
void F()
{
using stD::swap;
TEST::Dummy x;
swap(x);
}
void I()
{
using stD::sw;
int b = 0;
sw(b);
}
};
}
This is the error message:
../src/Test.h: In member function ‘void stD::aClass::F()’:
../src/Test.h:26:9: error: call of overloaded ‘swap(TEST::Dummy&)’ is ambiguous
swap(x);
^
../src/Test.h:26:9: note: candidates are:
../src/Test.h:17:6: note: void stD::swap(TEST::Dummy)
void swap(TEST::Dummy a){};
^
../src/Test.h:10:6: note: void TEST::swap(TEST::Dummy)
void swap(Dummy a){};
^
I thank you very much in advance for an answer.
This line is using argument dependent lookup
TEST::Dummy x;
swap(x);
So it will find both void stD::swap(TEST::Dummy) as well as void TEST::swap(TEST::Dummy) because x carries the TEST:: namespace.
In the latter case int b = 0; the variable b is not in a namespace, so the only valid function to call would be stD::sw due to your using statement.

Calling non template member function inside template member function

I am facing compilation problem while running the following program:
I am calling non template member function inside template member function but getting the weird compilation errors.
#include <iostream>
#include <boost\shared_ptr.hpp>
class base
{
public:
base()
{
}
void fun2(boost::shared_ptr<int> &data)
{
std::cout << "This is fun2" << std::endl;
}
void fun3(boost::shared_ptr<double> &value)
{
std::cout << "This is fun3" << std::endl;
}
template <typename T>
void fun1(int switchParam,T &resonse)
{
std::cout << "This is fun1." << std::endl;
switch(switchParam)
{
case 0:
fun2(resonse);
break;
case 1:
fun3(resonse);
break;
}
}
};
void main()
{
boost::shared_ptr<int> myInt;
int switchParam = 0;
base b1;
b1.fun1(switchParam,myInt);
}
Getting the following compilation problem:
Error 1 error C2664: 'base::fun3' : cannot convert parameter 1 from 'boost::shared_ptr<T>' to 'boost::shared_ptr<T> &'
Any help will be appreciated.
No. You cannot do that. With second phase of template code compilation for any type the switch block has to be fully compiled by compiler. It will will fail to compile. You are mixing templates with runtime behavior of program. You better write a different function.
Note that switch is runtime, not compile time. When you call it as fun1(0) the compiler still has to compile it fully for int. It won't evaluate runtime switch statement and eliminate fun3, which takes shared_ptr<double>.

No "redefinition of default parameter error" for class template member function?

Why does the following give no compilation error?:
// T.h
template<class T> class X
{
public:
void foo(int a = 42);
};
// Main.cpp
#include "T.h"
#include <iostream>
template<class T> void X<T>::foo(int a = 13)
{
std::cout << a << std::endl;
}
int main()
{
X<int> x;
x.foo(); // prints 42
}
It seems as though the 13 is just silently ignored by the compiler. Why is this?
The cooky thing is that if the class template definition is in Main.cpp instead of a header file, I do indeed get the default parameter redefinition error.
Now I know the compiler will complain about this if it were just an ordinary (non-template) function.
What does the standard have to say about default parameters in class template member functions or function templates?
8.3.6 §6 The default arguments in a member function definition that
appears outside of the class
definition are added to the set of
default arguments provided by the
member function declaration in the
class definition.
[Example:
class C {
void f(int i = 3);
void g(int i, int j = 99);
};
void C::f(int i = 3) // error: default argument already
{ } // specified in class scope
void C::g(int i = 88, int j) // in this translation unit,
{ } // C::g can be called with no argument
--end example]
According to the standard, it should give you an error.