Skip to content

Instantly share code, notes, and snippets.

@unixpickle
Created June 15, 2014 20:56
Show Gist options
  • Save unixpickle/4a52cf9dfeca0301e181 to your computer and use it in GitHub Desktop.
Save unixpickle/4a52cf9dfeca0301e181 to your computer and use it in GitHub Desktop.
Demonstrate covariant return thunk in C++
__ZN13FancyReturner7BaseRefEv: # the regular
00000001000014a0 pushq %rbp
00000001000014a1 movq %rsp, %rbp
00000001000014a4 movq %rdi, 0xfffffffffffffff8(%rbp)
00000001000014a8 movq 0xfffffffffffffff8(%rbp), %rdi
00000001000014ac addq $0x8, %rdi
00000001000014b3 movq %rdi, %rax
00000001000014b6 popq %rbp
00000001000014b7 ret
00000001000014b8 nopl (%rax,%rax)
...
__ZTch0_h8_N13FancyReturner7BaseRefEv: # the thunk
0000000100001b70 pushq %rbp
0000000100001b71 movq %rsp, %rbp
0000000100001b74 subq $0x10, %rsp
0000000100001b78 movq %rdi, 0xfffffffffffffff8(%rbp)
0000000100001b7c movq 0xfffffffffffffff8(%rbp), %rdi
0000000100001b80 callq 0x100001c68
0000000100001b85 addq $0x8, %rax
0000000100001b8b addq $0x10, %rsp
0000000100001b8f popq %rbp
0000000100001b90 ret
0000000100001b91 nopw %cs:(%rax,%rax)
#include <iostream>
using namespace std;
struct TheBase {
public:
int a;
};
class FancySubclass : public TheBase {
public:
virtual int GetA() {
return a;
}
};
class BaseReturner {
public:
virtual TheBase & BaseRef() = 0;
};
class FancyReturner : public BaseReturner {
public:
virtual FancySubclass & BaseRef() {
return instance;
}
FancySubclass instance;
};
int main() {
FancyReturner fancyRet;
BaseReturner & baseRet = fancyRet;
cout << "baseRet is " << (uintptr_t)&baseRet.BaseRef() << endl;
cout << "fancyRet is " << (uintptr_t)&fancyRet.BaseRef() << endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment