In C++ using clang++, is it possible to overload a method according to address-space qualifiers on the implicit ‘this’ parameter? If so, what is the syntax?
This source suggests that I can place the address-space qualifier after the parameter list but before the curly braces (similar to using the const qualifier on 'this'). I tried the following, but it failed; clang thinks I'm trying to set an address space of the method, rather than of 'this':
// Does not work.
struct SomeClass
{
// method for 'this' in default address space
void doit();
// method for 'this' in address space 300.
void doit() __attribute__((address_space(300)); // clang rejects this syntax
}
The closest I have found is that clang lets me overload a method according to the address spaces of its explicit formal parameters (not 'this'). For example, the code below will print “1\n2\n”.
// Similar, but does not solve my problem:
#include <cstdio>
struct SomeClass
{
void doit(void *v) { printf("1\n"); }
void doit(void __attribute__((address_space(300))) *v) { printf("2\n"); }
};
int main(int argc, char **argv)
{
SomeClass SC;
SC.doit( (void*) 0 );
SC.doit( (void __attribute__((address_space(300))) *) 0 );
return 0;
}
Related
This is a follow-up to my previous question: C++ compile error constructing object with rvalue std::string from which I learned about the Most Vexing Parse.
I understand now the gist of the problem, however there's one leftover item of syntax I still don't quite understand, which I'd like to ask as a standalone question, since the discussions on the previous post were getting quite long.
Given this code:
#include <iostream>
#include <string>
class Foo
{
public:
Foo(double d)
: mD(d)
{
}
Foo(const std::string& str)
{
try
{
mD = std::stod(str);
}
catch (...)
{
throw;
}
}
Foo(const Foo& other)
: mD(other.mD)
{
}
virtual ~Foo() {}
protected:
double mD;
};
class Bar
{
public:
Bar(const Foo& a, const Foo& b)
: mA(a)
, mB(b)
{
}
virtual ~Bar() {}
protected:
Foo mA;
Foo mB;
};
int main(int argc, char* argv[])
{
if (argc < 3) { return 0; }
Foo a(std::string(argv[1]));
Foo b(std::string(argv[2]));
Bar wtf(a, b);
}
I understand, now, that the line Foo a(std::string(argv[1])); can be interpreted as either:
(1) Create a Foo named a with an anonymous std::string that is created with a char*. (My desired interpretation)
or
(2) A declaration (not definition) for a function named a that takes a std::string*.
From answers to the original question, I learned that functions could be declared within the scope of another function. That was new to me, but seems within reason, I can buy it.
What I can't wrap my head around, though, is the interpretation of std::string(argv[1]) as a std::string*.
argv[1] is a char*, so I still don't see why the line isn't interpreted as an anonymous std::string being constructed with a char*. After all, I've used code analogous to the following hundreds of times without ever scrutinizing whether this would result in anything other than the construction of a std::string with its char* constructor:
#include <iostream>
int main()
{
char* pFoo[] = {"foo"};
std::string str(pFoo[0]);
std::cout << str << std::endl;
return 0;
}
I'm on the cusp of understanding the most vexing parse problem; if someone could further explain this last niggling part, that might help push me over the edge.
Thank you.
Foo a(std::string(argv[1]));
declares a function named a which returns Foo and has one parameter (named argv) of type std::string[1]. Since array function parameters are always replaced with pointer parameters, the actual type of the function parameter becomes std::string*.
Alright, I think the title is sufficiently descriptive (yet confusing, sorry).
I'm reading this library: Timer1.
In the header file there is a public member pointer to a function as follows:
class TimerOne
{
public:
void (*isrCallback)(); // C-style ptr to `void(void)` function
};
There exists an instantiated object of the TimerOne class, called "Timer1".
Timer1 calls the function as follows:
Timer1.isrCallback();
How is this correct? I am familiar with calling functions via function pointers by using the dereference operator.
Ex:
(*myFunc)();
So I would have expected the above call via the object to be something more like:
(*Timer1.isrCallback)();
So, what are the acceptable options for calling functions via function pointers, as both stand-alone function pointers and members of an object?
See also:
[very useful!] Typedef function pointer?
Summary of the answer:
These are all valid and fine ways to call a function pointer:
myFuncPtr();
(*myFuncPtr)();
(**myFuncPtr)();
(***myFuncPtr)();
// etc.
(**********************************f)(); // also valid
Things you can do with a function pointer.
1: The first is calling the function via explicit dereference:
int myfunc(int n)
{
}
int (*myfptr)(int) = myfunc;
(*myfptr)(nValue); // call function myfunc(nValue) through myfptr.
2: The second way is via implicit dereference:
int myfunc(int n)
{
}
int (*myfptr)(int) = myfunc;
myfptr(nValue); // call function myfunc(nValue) through myfptr.
As you can see, the implicit dereference method looks just like a normal function call -- which is what you’d expect, since function are simply implicitly convertible to function pointers!!
In your code:
void foo()
{
cout << "hi" << endl;
}
class TimerOne
{
public:
void(*isrCallback)();
};
int main()
{
TimerOne Timer1;
Timer1.isrCallback = &foo; //Assigning the address
//Timer1.isrCallback = foo; //We could use this statement as well, it simply proves function are simply implicitly convertible to function pointers. Just like arrays decay to pointer.
Timer1.isrCallback(); //Implicit dereference
(*Timer1.isrCallback)(); //Explicit dereference
return 0;
}
You don't have to dereference a function pointer to call it. According to the standard ([expr.call]/1),
The postfix expression shall have
function type or pointer to function type.
So (*myFunc)() is valid, and so is myFunc(). In fact, (**myFunc)() is valid too, and you can dereference as many times as you want (can you figure out why?)
You asked:
Timer1 calls the function as follows:
Timer1.isrCallback();
How is this correct?
The type of Timer1.isrCallback is void (*)(). It is a pointer to a function. That's why you can use that syntax.
It is similar to using:
void foo()
{
}
void test_foo()
{
void (*fptr)() = foo;
fptr();
}
You can also use:
void test_foo()
{
void (*fptr)() = foo;
(*fptr)();
}
but the first form is equally valid.
Update, in response to comment by OP
Given the posted definition of the class you would use:
(*Timer1.isrCallback)();
To use
(Timer1.*isrCallback)();
isrCallback has to be defined as a non-member variable of whose type is a pointer to a member variable of TimerOne.
void (TimerOne::*isrCallback)();
Example:
#include <iostream>
class TimerOne
{
public:
void foo()
{
std::cout << "In TimerOne::foo();\n";
}
};
int main()
{
TimerOne Timer1;
void (TimerOne::*isrCallback)() = &TimerOne::foo;
(Timer1.*isrCallback)();
}
Output:
In TimerOne::foo();
(Test this code)
If you want to define isrCallbak as a member variable of TimerOne, you'll need to use:
#include <iostream>
class TimerOne
{
public:
void (TimerOne::*isrCallback)();
void foo()
{
std::cout << "In TimerOne::foo();\n";
}
};
int main()
{
TimerOne Timer1;
Timer1.isrCallback = &TimerOne::foo;
// A little complicated syntax.
(Timer1.*(Timer1.isrCallback))();
}
Output:
In TimerOne::foo();
(Test this code)
I have the following function
static void p (){
}
I want to pass a function pointer to p into function x.
void x(void * ptr){
}
I am trying the following, and it is not working.
...
x(ptr);
Note x and p are in different classes.
I am getting the following compiling error.
invalid conversion from 'void (*)()' to 'void*' [-fpermissive]
It needs to be:
void x(void(*function)())
{
// Whatever...
}
If you're using C++11 you can std::function:
void x(std::function<void()> function)
{
// Whatever
}
Let's take a look at the error message:
invalid conversion from 'void (*)()' to 'void*' [-fpermissive]
It means that void* (a data pointer) is the type specified in x,
but void (*)() (a function pointer) is being passed instead.
So change x to
void x(void (*ptr)())
{
}
The answer is in the error message. void* is not a pointer to function, void(*)() (for example) is. You should rewrite x as follows :
void x(void (*ptr)()) {
}
A pointer-to-function is written this way :
Ret (*name)(Params)
Where
Ret is the pointee's return type
name is the name of the pointer
Params is the list ofthe pointee's parameters, as you would write them in its declaration.
Example :
double (*ptr)(int, float)
...can point to a function taking an int and a float and returning a double.
void* is not a function pointer, it's a void pointer.
To declare a function pointer, use void (*ptr)().
We can do some ugly pointer magic, like this:
static void function1( char* c ) {
printf( "%s", c );
}
void function2( void* ptr ) {
void(* func)(char*) = (void(*)(char*))ptr;
func( "a" );
}
int _tmain(int argc, _TCHAR* argv[])
{
void* f = function1;
function2( f );
return 0;
}
This is bad, but it works in such situations.
If I try to define a pointer to an overloaded function
void myprint(int );
void myprint(const char* );
void (*funpointer)(int) = myprint;
the compiler understands that funpointer should point to the version of myprint that matches its arguments. Instead, I want funpointer to be overloaded as well.
I tried simply adding a couple lines like
void myprint(int );
void myprint(const char* );
void (*funpointer)(int);
void (*funpointer)(const char *);
void funpointer = myprint;
but then the compiler complains of conflicting declarations for funpointer (obviously).
Is there a way to achieve what I'm looking for? I would like the pointer to behave as an overloaded function. So I could call it as either funpointer(1) or funpointer("Hey.") and it would work as the respective version of myprint.
Why are you doing this? Function pointers are for runtime polymorphism based on application state. Plain old overloads work fine if, the only variance is the argument type.
If you want to be able to, say write a library that will call overloads defined later, in client code, do something like the following:
void foo(int x) { printf("int\n");}
void foo(const char* c){ printf("char*\n"); }
template <class T> void callfoo(T t) { foo(t); }
int main(int argc, char* argv[])
{
int x = 3;
callfoo(x);
const char* p = "Hello world";
callfoo(p);
return 0;
}
This allows the lib to call overloads for types it is not actually aware of until link time.
No can do. You can't have two variables in the same scope with the same name.
Pointer is a Type, it cannot be overloaded. Only functions can be overloaded.
There is no way to achieve overloading of a pointer in C++.
You can't do it with function pointers... the argument list is part of the type, so any given function pointer can only correspond to one specific overload at a time. You might be able to fake it with function objects, though, depending on what you need to do.
struct MyPrint {
void operator()(int i) { int_f(i); }
void operator()(const char* c_str) { str_f(c_str); }
std::function<void(int)> int_f;
std::function<void(const char*) str_f;
};
void print_int(int i) { cout << i << endl; }
void print_string(const char* str) { cout << str << endl; }
int main() {
MyPrint p;
p.int_f = print_int;
p.str_f = print_string;
p(5);
p("Hi");
}
You lose the ability to just overload by name; you can't add a set_functions(f) that takes a function name and extracts both versions of the function. But as I showed, now you aren't limited to functions with the same name, or even just to functions. The object is also bigger than it used to be, and likely involves some heap allocations.
This might be considered "clunky", but you could do something like the following:
template<typename T>
struct funcptr_struct
{
typedef T type;
static type ptr;
};
template<> funcptr_struct<void(*)(int)>::type funcptr_struct<void(*)(int)>::ptr = myprint;
template<> funcptr_struct<void(*)(const char*)>::type funcptr_struct<void(*)(const char*)>::ptr = myprint;
You can then call each version of the myprint function using syntax like the following:
funcptr_struct<void(*)(int)>::ptr(5);
I had this problem happen to me in the past http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.19
My question is, when writing
Foo x(Bar());
Why is it "declaring a non-member function that returns a Bar object" ? i can understand it if i wrote
Foo x(Bar);
But what does it think the () means in Bar()?
Bar() there means "a function that takes no arguments and returns Bar". Consider a declaration of such a function:
Bar GetBar();
if you remove the name of the function from this, what remains will describe the function type. Some examples of where it's used is in template arguments; e.g. you can write this:
std::function<int(float)> f1;
std::function<Bar()> f2;
Hopefully this explains the syntax in general. Now what this means in this particular case. When a function type is used as a type of function argument, it is automatically subsituted for a function pointer type. So the equivalent (but clearer) declaration would be:
Foo x(Bar(*)());
Consider the following more simple example:
void fn1(int a)
{
}
fn1 is a function that takes a single int paramter.
Now take a look at fn2:
//Same as typing void fn2(int (*b)())
void fn2(int b())
{
}
Here fn2 does not take in an int, but it takes in a function that returns an int.
Now if you wanted to declare fn1 you could type it like so:
void fn1(int);//ommit the parameter name
And you can also declare fn2 like so:
void fn2(int());
Example usage:
#include <iostream>
int a()
{
sd::cout<<"hi"<<std::endl;
return 0;
}
void fn2(int b())
{
b();
}
int main(int argc, char **argv)
{
fn1(3);
fn2(a);
}
Output will be:
hi
Now there is one more topic to understand... You can forward declare functions with scope.
a.cpp:
void a()
{
void c();
c();
}
//void b()
//{
// c();//<--- undeclared identifier
//}
int main(int argc, char**argv)
{
a();
return 0;
}
c.cpp
#include <iostream>
void c()
{
std::cout<<"called me"<<std::endl;
}
g++ a.cpp c.cpp
./a.out
Output will be:
Called me
And tying it all together. If you do this:
int main(int argc, char**argv)
{
int b();
return 0;
}
You are forward declaring a function called b() that returns type int and takes no parameters
If you would have done b = 3; then you'd get a compiling error as you can't assign a value to a forward declared function.
And once you've read all that it becomes clear:
Foo x(Bar());
You are forward declaring a function x that returns a type Foo and takes in a parameter to a function that returns a type Bar.
Unfortunately it doesn't seem to be online, but Scott Meyers' book, Effective STL, has a good, detailed explanation of what's going on in your example in Item 6: Be alert for C++'s most vexing parse.
On the plus side, the book is worth the price for anyone serious about C++.