-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathtypefetch.h
More file actions
83 lines (71 loc) · 2.6 KB
/
typefetch.h
File metadata and controls
83 lines (71 loc) · 2.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/**
* typefetch.h - Aliasing nearly all types using state-full metaprogramming
* Curated by: Pufeng Du.
*
* Warning: This is not officially supported in standard.
*
* Notes:
* This is a demo to use the well-known 'loophole bug' to bind almost any type
* to a name that can be used in compile time. Private member type can be extracted
* in this way.
* This is NOT authored by me. I only curated pieces of codes from Github and Zhihu
* with some modifications.
*
* References:
* https://stackoverflow.com/questions/65190015/c-type-loophole-explanation
* https://alexpolt.github.io/type-loophole.html
* https://www.zhihu.com/question/663583917/answer/3590252149
*
* Usage:
* BIND_TYPE(type_name, expression_to_extract_type, unique_id_for_the_type)
* BIND_TYPE must be used in file scope, out of all fucntions.
* type_name: The type alias name.
* expression_to_extract_type: like any expression you put in decltype(). However,
* this expression will NOT be evaluated. The private scope restriction will NOT be
* checked.
* unique_id_for_the_type: a positive integer, uniquely binded to the type, to
* tell which type is which. You may use your own macro skills to optimize this part.
* Like creating some tricks to make it increasing automatically.
*/
#ifndef TYPEFETCH_H_INCLUDED
#define TYPEFETCH_H_INCLUDED
template <size_t N>
struct tag{};
template <typename T, size_t N>
struct type_fetch_t{
// This assumes that T supports default aggregate initialization
friend auto internal_type(tag<N>){return T{};}
};
#define BIND_TYPE(TYPENAME, EXPR, TYPE_ID) \
auto internal_type(tag<TYPE_ID>); \
template struct type_fetch_t<decltype(EXPR), TYPE_ID>; \
using TYPENAME = decltype(internal_type(tag<TYPE_ID>{}));
#endif // TYPEFETCH_H_INCLUDED
/*
// This is a use case, to extract the type of a private
// member function of a given class A. The type of the
// private member function is binded with an alias
// method_t. Please note that the private member does not
// need to be implemented.
#include <iostream>
#include "typefetch.h"
using namespace std;
class A{
private:
int a_private_method();
};
BIND_TYPE(method_t, A::a_private_method, 0);
template<typename T>
string CompileTimeTypeName() {
string func_name = __PRETTY_FUNCTION__;
size_t _s = func_name.find("T = ") + 4;
size_t _e = func_name.find(";", _s);
string r = func_name.substr(_s, _e - _s);
return r;
}
int main() {
// The output should be
// int (A::*)()
cout << CompileTimeTypeName<method_t>() << endl;
}
*/