I am using C++ in native mode with Visual Studio 2017 and I am trying to compile and run the example code found at Debugging a Parallel Application in Visual Studio.
For the record, I program in C not C++. I am clueless when it comes to method declarations (among many other things). I suspect correcting the error is simple but, I simply don't know how.
In other words, I am currently RTFineM. I simply copied and pasted the example given in the url above and ran into 2 problems. First it complained about something being deprecated but a simple define took care of that problem. Second it complained about not being able to convert a type into another as stated in the title.
The RunFunc class causing the problem is declared as follows:
class RunFunc
{
Func& m_Func;
int m_o;
public:
RunFunc(Func func,int o):m_Func(func),m_o(o)
{
};
void operator()()const
{
m_Func(m_o);
};
};
My question/request is: how does the declaration of RunFunc need to be in order for the example to compile and run properly ?
Thank you, much appreciate the help.
In this constructor
RunFunc(Func func,int o):m_Func(func),m_o(o)
{
};
the prameter Func func is adjusted by the compiler to the type Func *func. On the other hand the data member m_Func is declared as a referenced type.
Func& m_Func;
And the error message says about incompatibility of the types.
C2440 cannot convert from 'void (_cdecl*)(int)' to 'void(_cdecl&)(int)
Try to declare the constructor like
RunFunc(Func &func,int o):m_Func(func),m_o(o)
{
};
Or declare the data member like
Func *m_Func;
without changing the constructor.
Here are two demonstrative programs
#include <iostream>
typedef void Func( int );
class RunFunc
{
Func& m_Func;
int m_o;
public:
RunFunc(Func &func,int o):m_Func(func),m_o(o)
{
};
void operator()()const
{
m_Func(m_o);
};
};
int main() {
return 0;
}
and
#include <iostream>
typedef void Func( int );
class RunFunc
{
Func *m_Func;
int m_o;
public:
RunFunc(Func func,int o):m_Func(func),m_o(o)
{
};
void operator()()const
{
m_Func(m_o);
};
};
int main() {
return 0;
}
In your code you are tyring to bound a reference to a temporary, namely to copy of argument passed to the constructor. You can try to run the following code snippet to see the difference:
struct Func {
int _i;
void operator()(int i) { cout << i*_i << endl; }
};
class RunFunc
{
Func& m_Func;
int m_o;
public:
RunFunc(Func &func, int o) :m_Func(func), m_o(o)
// RunFunc(Func func, int o) :m_Func(func), m_o(o)
{
};
void operator()()const
{
m_Func(m_o);
};
};
int main() {
Func f{ 5 };
RunFunc rf(f, 2);
rf();
return 0;
}
This is a legacy approach. You can use standard library functor and binder instead. For example:
#include <functional>
#include <iostream>
static void my_callback(int i) {
std::cout<< i << std::endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
std::function<void()> functor;
functor = std::bind(my_callback, 1);
functor();
return 0;
}
Related
Consider following code snippet:
class Foo {
public:
void bar(std::size_t){}
void bar(const char* ){}
};
int main() {
auto foo = Foo{};
foo.bar(0);
}
It produces ambiguous calls errors (check here). But I think from programmer's perspective it is pretty obvious that I want to call overload with std::size_t. My question is if anything can be done so this code does not produce errors and calls size_t overload?
can be done like this in C++ 20
#include <cstdint>
#include <iostream>
#include <type_traits>
class Foo {
public:
template <typename T>
requires std::is_integral_v<T>
void bar(T){
std::cout<<"hello size_T";
}
void bar(const char* ){
std::cout<<"hello";
}
};
int main() {
auto foo = Foo{};
foo.bar(25);
}
In modern c++ (at least c++17), we prefer to pass string_view as argument over const char* for the none owner transfer cases, so a considerable choice:
#include <cctype>
#include <string>
class Foo {
public:
void bar(std::size_t){}
void bar(std::string_view){}
};
int main() {
auto foo = Foo{};
foo.bar(0);
}
Online demo
In below C++ 20, this works well.
#include <iostream>
class Foo {
public:
template <typename T>
void bar(T) {
std::cout << "hello T" << std::endl;
}
void bar(const char* c) {
std::cout << c << std::endl;
}
};
int main() {
auto foo = Foo{};
foo.bar(0);
foo.bar("test.");
}
This works in C++23:
foo.bar(0zu);
and this works pre-C++23:
foo.bar(size_t{0});
I need to be able to specify a function for a class to be able to run (a callback function?) as part of a menu system, my knowledge of c++ is stretched here. Obviously this won't compile but hopefully it gives an idea of what I'm trying to do -
void testFunc(byte option) {
Serial.print("Hello the option is: ");
Serial.println(option);
}
typedef void (*GeneralFunction)(byte para);
GeneralFunction p_testFunc = testFunc;
class testClass {
GeneralFunction *functionName;
public:
void doFunction() {
functionName;
}
};
testClass test { *p_testFunc(123) };
void setup() {
Serial.begin(9600);
test.doFunction();
}
void loop() {
}
I am aware of some std:: options but Arduino doesn't have them implemented unfortunately.
Edit: The compiler output for this code -
sketch_mar10a:17:29: error: void value not ignored as it ought to be
testClass test { *p_testFunc(123) };
^
sketch_mar10a:17:35: error: no matching function for call to 'testClass::testClass(<brace-enclosed initializer list>)'
testClass test { *p_testFunc(123) };
^
Please find the below code, see if this helps,you need a constructer to take the parameter, also you can't call the function from the parameter list while its expecting a function pointer
#include <iostream>
using namespace std;
void testFunc(int option) {
std::cout<<"in fn "<<option;
}
typedef void (*GeneralFunction)(int para);
GeneralFunction p_testFunc = testFunc;
class testClass {
GeneralFunction functionName;
int param1;
public:
testClass(GeneralFunction fn,int par1):functionName(fn),param1(par1){}
void doFunction() {
functionName(param1);
}
};
testClass test (p_testFunc,123);
void setup() {
test.doFunction();
}
void loop() {
}
int main()
{
setup();
return 0;
}
Thanks to Bibin I have adapted his code to suit Arduino, separated the constructor, and initialized the class in setup().
void testFunc(byte option) {
Serial.print("Hello the option is: ");
Serial.println(option);
}
typedef void (*GeneralFunction)(byte para);
GeneralFunction p_testFunc = testFunc;
class testClass {
GeneralFunction functionName;
byte param1;
public:
testClass(GeneralFunction fn, int par1);
void doFunction() {
functionName(param1);
}
};
void setup() {
Serial.begin(9600);
testClass test (p_testFunc, 123);
test.doFunction();
}
void loop() {
}
testClass::testClass(GeneralFunction fn, int par1) //constructor
: functionName(fn), param1(par1) {}
Which outputs:
Hello the option is: 123
I am trying to use a custom comparator as in the following minimal example:
#include <set>
using namespace std;
struct idComp;
class TestClass
{
public:
int id;
void setId(int i){ id = i; }
int getId(){ return id; }
void test( set<TestClass*, idComp> &s){
//do my stuff
}
void test2(){
set <TestClass*, idComp> s;
}
};
struct idComp
{
bool operator() (TestClass* t1, TestClass* t2) const
{
return t1->getId() < t2->getId();
}
};
int main(int argc, char* argv[])
{
return 0;
}
...but when I try to compile I get the following error relating to the test function:
comp_ref.cpp:12:34: error: ‘idComp’ was not declared in this scope
void test( set<TestClass*, idComp> &s){
^~~~~~
comp_ref.cpp:12:40: error: template argument 2 is invalid
void test( set<TestClass*, idComp> &s){
and this with the addition of test2:
/usr/include/c++/7/bits/stl_tree.h:708:31: error: invalid use of incomplete type ‘struct idComp’
_Rb_tree_impl<_Compare> _M_impl;
Any suggestions of how/where to define idComp so that it is usable by the function test?
Since you have a bit of a circular dependency, you can resolve this by forward-declaring idComp before TestClass:
struct idComp;
class TestClass
{
...
But you can leave the definition of struct idComp where it is.
I just realized that trying to get the return type of a function via decltype does not involve ADL (argument-dependent-lookup) on VS2012 (tested using cl.exe V17.00.60610.1).
The following example
#include <stdio.h>
#include <typeinfo>
namespace A {
int Func(void const *) {
printf("A::Func(void const *)\n");
return 0;
}
template <typename T> void Do(T const &t) {
Func(&t);
}
template <typename T> void PrintType(T const &t) {
printf("Type: %s\n", typeid(decltype(Func(&t))).name());
}
}
namespace B {
struct XX { };
float Func(XX const *) {
printf("B::Func(XX const *)\n");
return 0.0f;
}
}
int main(int argc, char **argv) {
B::XX xx;
A::Do(xx);
A::PrintType(xx);
return 0;
}
Gives
B::Func(XX const *)
Type: int
on VS2012
but (what is expected):
B::Func(XX const *)
Type: f
on gcc 4.7.3.
So ADL works when calling the function (line 1 in output) but not when used inside decltype on VS2012.
Or am I missing some different point?
A minimal test case is:
namespace N
{
struct C {};
C f(C) {};
}
N::C c1;
decltype(f(c1)) c2;
If the compiler doesn't support ADL inside decltype, then the above will not compile.
I'm told it does compile, so maybe it is the interaction between ADL and template instantiation that is the problem.
If find it amusing that the IDE/Intellisense whatsoever seems to do the lookup correctly but the compiler does not.
This example shows no intellisense errors and a is displayed to be of type size_t when hovering it.
#include <iostream>
namespace A
{
struct C {};
size_t f(C*) { return 5U; };
}
namespace B
{
void f(void *) { };
void f2 (A::C x)
{ decltype(f(&x)) a; std::cout << typeid(a).name() << std::endl; }
}
int main (void)
{
A::C c;
B::f2(c);
}
The compiler stops with Error C2182 and complains about a variable of type void.
It seems to be a problem independant of templates.
I am trying to create a generic function map using templates.The idea is to inherit from this generic templated class with a specific function pointer type. I can register a function in the global workspace, but I'd rather collect all the functions together in the derived class and register these in the constructor. I think I am almost here but I get a compile error. Here is a stripped down version of my code:
#include <iostream>
#include <string>
#include <map>
#include <cassert>
using namespace std;
int f(int x) { return 2 * x; }
int g(int x) { return -3 * x; }
typedef int (*F)(int);
// function factory
template <typename T>
class FunctionMap {
public:
void registerFunction(string name, T fp) {
FunMap[name] = fp;
}
T getFunction(string name) {
assert(FunMap.find(name) != FunMap.end());
return FunMap[name];
}
private:
map<string, T> FunMap;
};
// specific to integer functions
class IntFunctionMap : public FunctionMap<F> {
public:
int f2(int x) { return 2 * x; }
int g2(int x) { return -3 * x; }
IntFunctionMap() {
registerFunction("f", f); // This works
registerFunction("f2", f2); // This does not
}
};
int main()
{
FunctionMap<F> fmap; // using the base template class directly works
fmap.registerFunction("f", f);
F fun = fmap.getFunction("f");
cout << fun(10) << endl;
return 0;
}
The error I get is:
templatefunctions.cpp: In constructor ‘IntFunctionMap::IntFunctionMap()’:
templatefunctions.cpp:33: error: no matching function for call to ‘IntFunctionMap::registerFunction(const char [3], <unresolved overloaded function type>)’
templatefunctions.cpp:15: note: candidates are: void FunctionMap<T>::registerFunction(std::string, T) [with T = int (*)(int)]
Juan's answer is correct: member functions have an implicit first parameter, which is a pointer to the type of which they are a member. The reason your code fails to compile is that your map supports function pointers with type int (*)(int), but the type of f2 is int (IntFunctionMap::*)(int).
In the specific case that you show here, you can use std::function, which implements types erasure, to present free functions and member functions as the same type. Then you could do what you are trying to do. Note: this requires C++11.
#include <iostream>
#include <string>
#include <map>
#include <cassert>
#include <function>
#include <bind>
using namespace std;
int f(int x) { return 2 * x; }
int g(int x) { return -3 * x; }
typedef std::function<int (int)> F;
// function factory
template <typename T>
class FunctionMap {
public:
void registerFunction(string name, T fp) {
FunMap[name] = fp;
}
T getFunction(string name) {
assert(FunMap.find(name) != FunMap.end());
return FunMap[name];
}
private:
map<string, T> FunMap;
};
// specific to integer functions
class IntFunctionMap : public FunctionMap<F> {
public:
int f2(int x) { return 2 * x; }
int g2(int x) { return -3 * x; }
IntFunctionMap() {
registerFunction("f", f); // This works
registerFunction("f2", std::bind(&f2, this, _1)); // This should work, too!
}
};
int main()
{
FunctionMap<F> fmap; // using the base template class directly works
fmap.registerFunction("f", f);
F fun = fmap.getFunction("f");
cout << fun(10) << endl;
return 0;
}