decltype(function) as class member - c++

I have:
int foo(int x) { return x+1; }
struct Bar {
decltype(foo) operator();
};
int main() {
Bar bar;
printf("%d\n",bar(6));
}
which results in the slightly startling compiler error message (g++ 4.6.1):
error: declaration of 'operator()' as non-function
When changing the member name to
decltype(foo) blubb;
and using it results in a linker error:
undefined reference to `Bar::blubb(int)'
Is this expected behaviour?

It seems that you want to "copy" the signature of another function to create a function with the same signature. Since decltype(foo) is indeed the type of the function (and not a pointer to that function, which would be decltype(&foo) and would lead to a pointer declaration), you can use it to declare a function with the same signature as another function.
As indicated by the linker error:
undefined reference to `Bar::blubb(int)'
this will already work fine with your compiler. However it seems that gcc did not yet fully implement this part of the standard, as it will not accept the syntax for the same thing with a function call operator. Clang btw. will happily accept it and the link then errors out with
undefined reference to `Bar::operator()(int)'
Your question about why that linker error exists indicates a misunderstanding of what decltype really does.
It will just evaluate to a type, not more. The definition of blubb is in no way tied to the definition of foo. This might be clearer when writing it like
typedef decltype(foo) x;
x blubb;
You can now alternatively typedef x to be explicitly the function type, which will not in any way change what blubb is. You still need to define it. And since there is no syntax to define it using decltype, you explicitly have to write it as
int Bar::operator()(int) {
...
}
which will likely and unfortunately defeat the purpose/benefit of using decltype for the declaration, as it will not allow you to automatically "copy" a signature.

This is a wild guess based on observing your usage of printf here:
printf("%d\n",bar(6));
This lets me assume you really want the return type of the function, not the type of the function. If so, then you use decltype wrong. You get the return type of the function by "simulating" the usage of the function, i.e.
decltype(foo(0)) operator() (int);
should be the right thing for you. Otherwise, if that was not your attention, you are skating on thin ice by giving a function type (and not function return type) to the %d specifier.
Generally, the meaning of decltype is: decltype(#) gives the static type of the expression #.

This should work.
I just used it here to capture whatever gobbledygook std::bind was going to give me:
class RiceFadingModel::Impl
{
public:
Impl(double K, double A)
: //...
_M_re{system_now()},
_M_rd{_M_nu, _M_sigma},
_M_gen{std::bind(_M_rd, _M_re)}
{ }
private:
//...
std::default_random_engine _M_re;
/// The underlying Rice distribution.
__gnu_cxx::__rice_distribution<double> _M_rd;
/// The variate generator built from the pseudo-random number engine and the Rice distribution.
decltype(std::bind(_M_rd, _M_re)) _M_gen;
};
This works like a charm on gcc-4.7. Now that I think about it I built it on mingw with gcc-4.5 too.

Related

Explicitly passing *this in C++

While reading about *this, I saw:
When a nonstatic member function is called for an object, the compiler
passes the object's address to the function as a hidden argument.
Then I tried:
#include <iostream>
class MyClass
{
int myVar;
public:
MyClass(const int& val) : myVar{val} {}
// int getVar(MyClass* this) <-- Error: expected ',' or '...' before 'this'
int getVar()
{
return this->myVar;
}
};
int main()
{
MyClass obj(22);
// std::cout << obj.getVar(&obj); <-- Error: no matching function
// std::cout << MyClass::getVar(&obj); <-- Error: no matching function
std::cout << obj.getVar();
return 0;
}
Why am I not able to access the hidden argument? Is it called 'hidden' because of that?
Are only compilers allowed to do this? Can't we explicitly mention *this in the function signature?
The closest answer I've found before asking this is this. But I tried that way and still got the error. Could I get an explanation of those error messages? Because, if the compiler actually modifies those function signatures to contain *this then that should have worked, isn't it?
Are only compilers allowed to do this?
Precisely. That's why it's called hidden: It's something that the compiler does on your behalf, but which is hidden from the C++ code that uses it.
The compiler must pass the this pointer to the member function somehow, but it does not need to tell you how it does it. It could compile the code to the equivalent of MyClass::getVar(&obj), passing the this pointer in the same way that it would pass the argument for the C function free(foo). Or it might use a different mechanism that is totally incompatible with non-member argument passing. What it does under the hood is defined by the platform's Abstract Binary Interface standard (ABI), which is not part of the C++ language standard. What happens under Windows could be vastly different from what happens under Linux, and Linux on ARM could be different from Linux on X86, etc.
That said, you can take a look at what actually happens by telling your compiler to produce the assembly code. For gcc, the incantation would be
g++ -S -Os interestingCode.cpp
This will produce a .s file that contains how g++ actually translated your code.
obj.getVar(&obj)
This version cannot compile because the getVar() member function is not declared to take any parameters.
MyClass::getVar(&obj)
This version is using the syntax to access a static function but getVar() is not static, nor does it accept any parameters.
Note: The obj.getVar() call works because it is specifying which object instance to use (i.e., the obj. part) to execute the member function and is conceptually how the member function is passed the this pointer.
When you are doing obj.getVar() it is already explicitly specified the pointer *this=&obj and passed implicitly to getVar. It is not hidden. It is explicitly passed leftside of the function. You can use obj.getVar() or ptrObj->getVar() but in C++ is not allowed to use such construction getVar(thisptr). Hidden means the variable named this is nowhere declared, but you can use inside the function.

function pointers and return type conversions

Suppose I have a function that performs some side effect and then returns an answer:
int foo()
{
perform_some_side_effect();
return 42;
}
I want to bind foo to a function pointer, but I'm not interested in the answer, just the side effect:
void (*bar)() = foo;
However, this appears to be a type error:
error: invalid conversion from ‘int (*)()’ to ‘void (*)()’
What is the rationale behind that error? Why doesn't the type system allow me to ignore the answer?
On a side note, it works if I wrap the function pointer in a std::function:
std::function<void()> baz = foo;
How does std::function (apparently) manage to circumvent this restriction in the type system?
What is the rationale behind that error? Why doesn't the type system allow me to ignore the answer?
The reason is that the types are different, and the generated code at the place of call (through the function pointer) is different. Consider a calling convention where all arguments are written to the stack and space for the return value is also reserved in the stack. If the call goes through a void (*)() then no space will be reserved in the stack for the return value, but the function (unaware of how it is being called) will still write the 42 to the location where the caller should have reserved space.
How does std::function (apparently) manage to circumvent this restriction in the type system?
It does not. It creates a function object that wraps the call to the actual function. It will contain a member like:
void operator()() const {
foo();
}
Now when the compiler processes the call to foo it knows what it has to do to call a function that returns an int and it will do so according to the calling convention. Because the template does not return, it will just ignore the value --that was actually returned.
std::function need only be source compatible- that is, it can generate a new class which generates new caling code that ignores the result. The function pointer must be binary compatible and cannot do that job- void(*)() and int(*)() point to the exact same code.
You can think of std::function<> doing this for your particular case:
void __func_void()
{
foo();
}
It's actually a bit more complicated than that, but the point is that it generates template code together with type-erasure to not care about the specifics.
In addition to what others have been saying, the caller also need the return type to know what destructor it should invoke on the result (the return value may be a temporary).
Unfortunately it is not as easy as
auto (*bar)() = foo;
Although GCC and Clang accept this. I need to recheck the spec to see whether that's actually correct.
Update: The spec says
The auto type-specifier signifies that the type of a variable being declared shall be deduced from its initializer or that a function declarator shall include a trailing-return-type.
This can be misleading when read fast, but this is implemented by GCC and clang to only apply to the toplevel declarator. In our case, this is a pointer declarator. The declarator nested in it is a function declarator. So just substitute auto for void and then the compiler will deduce the type for you.
By the way, you can always make this work manually, but it takes some trickery to make it work
template<typename FunctionType>
struct Params;
template<typename ...Params>
struct Params<void(Params...)> {
template<typename T>
using Identity = T;
template<typename R>
static Identity<R(Params...)> *get(R f(Params...)) {
return f;
}
};
// now it's easy
auto bar = Params<void()>::get(foo);

C++ typedef member function signature syntax

I want to declare type definition for a member function signature. Global function typedefs look like this:
typedef int (function_signature)(int, int);
typedef int (*function_pointer) (int, int);
But I'm not able to the same thing for a member function:
typedef int (foo::memberf_signature)(int, int); // memberf_pointer is not a member of foo
typedef int (foo::*memberf_pointer)(int, int);
It sounds logically to me, because foo:: is the syntax to access a member in the class foo.
How can I typedef just the signature?
For questions regarding the awkward function pointer syntax, I personally use a cheat-sheet: The Function Pointers Tutorial (downloadable here, thanks to Vector for pointing it out).
The signature of a member function, however, is a bit different from the signature of a regular function, as you experienced.
As you probably know, a member function has a hidden parameter, this, whose type need be specified.
// C++11 and above.
using Member = int (Foo::*)(int, int);
// C++03 and below.
typedef int (Foo::*Member)(int, int);
does let you specify that the first element passed to the function will be a Foo* (and thus your method really takes 3 arguments, when you think of it, not just 2.
However there is another reason too, for forcing you to specify the type.
A function pointer might refer to a virtual function, in which case things can get quite complicated. Therefore, the very size of the in-memory representation changes depending on the type of function. Indeed, on Visual Studio, a function pointer's size might vary between 1 and 4 times the size of a regular pointer. This depends on whether the function is virtual, notably.
Therefore, the class the function refers to is part of the signature, and there is no work-around.
You can factor out the target class in modern C++ (post 11) by utilizing the 'typedefing' qualities of template aliases. What you need would look like like:
template<typename T>
using memberf_pointer = int (T::*)(int, int);
Yet at the point of declaration, a pointer to member function utilizing this syntax would need to specify the target class:
// D is a member function taking (int, int) and returning int
memberf_pointer<foo> mp = &foo::D;
The reason it doesn't work with your current syntax is that operator precedence dictates that you're referring to a function named foo::memberf_signature, not any sort of type.
I don't know for sure if you can do this or not, but I couldn't come up with any combination of parenthese that induced the code to compile with g++ 4.2.
It works for me:
#include <iostream>
class foo
{
public:
int g (int x, int y) { return x + y ; }
} ;
typedef int (foo::*memberf_pointer)(int, int);
int main()
{
foo f ;
memberf_pointer mp = &foo::g ;
std::cout << (f.*mp) (5, 8) << std::endl ;
}
Well basically it can't work (at least I know no way using g++);
Using borland c++ compiler there would be the __closure keyword.
The reason why it does not compile is, that sizeof the functionpointer (on a x86 machine) occupies always <<32bits>>; but if you want to point to a class (interface) signature, the sizeof has to be 64bit: 32 bit for the this pointer (as the class interface is in the memory only once) and 32 bit for the actual function
But the __closure keyword is a bcb language 'hack' not standardized...

int transforms into int&?

code snippet:
// some code
SDL_Surface* t = Display->render_text(text);
int z=100;
Display->blit_image(t,z,100);
// some more code
does not compile because z magically changes to an int&,
file.cpp:48: error: no matching function for call to ‘display::blit_image(SDL_Surface*&, int&, int)
how can this happen?
post scriptum:
the following works if i put them in place of Display->blit_image(t,z,100)
Display->blit_image(t,z,100,0);
but i am sure that th 4th param is optional because the exact same function works elsewhere without it
pps: i created a minimal-case of my code that behaves as describd above
it's 3 files:
monkeycard.cpp: http://pastebin.com/pqVg2yDi
display.hpp: http://pastebin.com/xPKgWWbW
display.cpp: http://pastebin.com/nEfFX1wj
g++ -c display.cpp monkeycard.cpp fails with:
monkeycard.cpp: In member function ‘void monkeycard::messagebox(std::string)’:
monkeycard.cpp:28: error: no matching function for call to ‘display::blit_image(SDL_Surface*&, int&, int)’
display.hpp:26: note: candidates are: void display::blit_image(SDL_Surface*, int, int, SDL_Rect*)
The error message tells you what you're trying to pass. With automatic conversions and whatnot, that doesn't mean the function must have exactly that signature.
int& here just means that the parameter you've provided is an lvalue, and so it could be passed as a non-const reference. A function can match with that parameter as an int&, const int&, int, long, const float&, etc.
the point is that if instead of z i
write 100 it works.
That's interesting. I can't immediately think of a way to write a function that accepts an integer literal, but not an integer variable. The following code compiles, of course:
struct SDL_Surface;
struct SDL_Rect;
struct display {
void foo(SDL_Surface* img, int x=0, int y=0, SDL_Rect* clip=0) {}
};
int main() {
display d;
int z = 0;
SDL_Surface *p = 0;
d.foo(p,z,100);
}
So there must be something else you haven't mentioned yet, which causes the issue.
Edit: visitor and Charles Bailey (in a comment) have the answer. The defaults are missing from your declaration of the function, so as far as the compiler is concerned you are trying to call a 4-parameter function with 3 arguments. The & is not the problem.
For future reference: when James McNellis asked you for "the" declaration of your function, he meant the declaration which is visible in the translation unit making the call. In your pastebin code, the definition is not visible in that translation unit, and the compiler cannot reach in to a completely different .cpp file and realise that the function is supposed to have parameter defaults. In C++, default values are set up in the calling code, for reasons to do with how calling conventions work.
Having seen the code, the defaults should be given in the header and not in the implementation file.
When you are compiling "monkeycard.cpp", the compiler has only the information in the headers to work with. The compiler has no idea that blit_image has default arguments, and therefore cannot match the function to call.
I suspect that the function isn't declared properly.
There needs to be a prototype inside the class display scope such as:
void blit_image(SDL_Surface* img, int x=0, int y=0, SDL_Rect* clip=NULL);
When you pass an int & parameter (such as any named variable of type int) to an int argument, the value of the int & is copied into the new object of type int. The difference in types implies a conversion which entails a copy which implements pass-by-value. That is just how the C++ formalism works.
The error message you see is nothing else than a specific convention, which that particular compiler uses to generate error messages in cases like that. Apparently, when the compiler is unable to resolve a function call, it generates an error message where every Lvalue argument is reported as having reference type and every Rvalue argument is reported as having non-reference type. This makes some sense, since references in C++ exist specifically for implementing the concept of run-time-bound Lvalue. In fact, it might even turn out that this is exactly how the overload resolution is implemented internally in that compiler.
As for the reason for the error: the function you are trying to call does not exist (or exists, but has a non-matching set of parameters).
P.S. You said in the comments that the matching function actually does exist. That would mean that there's either a problem with the visibility of the function declaration, or a problem with the code you posted being "fake" (i.e. it is not the code you were actually compiling).
Primitives are not reference types in C++.
How do you know that it's the int& that's the cause for the error? The error simply says that the signature is in error. I'd recommend going back and checking the method signature to see what the root cause is.

C++ enum not properly recognized by compiler

Can anyone explain why the following code does not compile (on g++ (GCC) 3.2.3 20030502 (Red Hat Linux 3.2.3-49))?
struct X {
public:
enum State { A, B, C };
X(State s) {}
};
int main()
{
X(X::A);
}
The message I get is:
jjj.cpp: In function 'int main()':
jjj.cpp:10: 'X X::A' is not a static member of 'struct X'
jjj.cpp:10: no matching function for call to 'X::X()'
jjj.cpp:1: candidates are: X::X(const X&)
jjj.cpp:5: X::X(X::State)`
Is this bad code or a compiler bug?
Problem solved by Neil+Konrad. See the comments to Neil's answer below.
You've forgot the variable name in your definition:
int main()
{
X my_x(X::A);
}
Your code confuses the compiler because syntactically it can't distinguish this from a function declaration (returning X and passing X::A as an argument). When in doubt, the C++ compiler always disambiguates in favour of a declaration.
The solution is to introduce redundant parentheses around the X since the compiler forbids parentheses around types (as opposed to constructo calls etc.):
(X(X::A));
X(X::A);
is being seen a s a function declaration. If you really want this code, use:
(X)(X::A);
Just to make it crystal clear what happens. Look at this example
int main() {
float a = 0;
{
int(a); // no-op?
a = 1;
}
cout << a;
}
What will it output? Well, it will output 0. The int(a) of above can be parsed in two different ways:
Cast to int and discard the result
Declare a variable called a. But ignore the parentheses around the identifier.
The compiler, when such a situation appears where a function-style cast is used in a statement and it looks like a declaration too, will always take it as a declaration. When it can't syntactically be a declaration (the compiler will look at the whole line to determine that), it will be taken to be an expression. Thus we are assigning to the inner a above, leaving the outer a at zero.
Now, your case is exactly that. You are trying (accidentally) to declare an identifier called A within a class called X:
X (X::A); // parsed as X X::A;
The compiler then goes on to moan about a not declared default constructor, because the static, as it assumes it to be, is default constructed. But even if you had a default constructor for X, it of course is still wrong because neither A is a static member of X, nor a static of X can be defined/declared at block scope.
You can make it not look like a declaration by doing several things. First, you can paren the whole expression, which makes it not look like a declaration anymore. Or just paren the type that is cast to. Both of these disambiguations have been mentioned in other answers:
(X(X::A)); (X)(X::A)
There is a similar, but distinct ambiguity when you try to actually declare an object. Look at this example:
int main() {
float a = 0;
int b(int(a)); // object or function?
}
Because int(a) can be both the declaration of a parameter called a and the explicit conversion (cast) of the float-variable to an int, the compiler decides again that that is a declaration. Thus, we happen to declare a function called b, which takes an integer argument and returns an integer. There are several possibilities how to disambiguate that, based on the disambiguation of above:
int b((int(a))); int b((int)a);
You should declare an object as
X x(X::A);
Bug in your code.
Either of these two lines work for me:
X obj(X::A);
X obj2 = X(X::A);
As Neil Butterworth points out, X(X::A) is being treated as a function declaration. If you really want an anonymous object, (X)(X::A) will construct an X object and immediately delete it.
You could, of course, just do something like this:
int main()
{
// code
{
X temp(X::A);
}
// more code
}
This would be more readable and basically have the same effect.