I have one question with boost.pfr.
Anthony Polukhin made use of Alexandr Poltavsky(https://alexpolt.github.io/type-loophole.html)'s technique to register deduced struct field information. Basically, because C++ has no built-in reflection, Mr. Polukhin used converting operator 'template operator T(){...}' to detect fields of a class. For a POD aggregate class like
struct A{int val1;...};
He would use
struct U1{
template<typename T>operator T(){...};
};
to initialize the struct like
A a{U1()};
for which U1's converting operator will be called and he resorts to Poltavsky's technique to save the deduced class. I speculate that this was because:
Poltavsky's loophole essentially
I appreciate both Polukhin and Poltavsky's ingenuities and try to experiment with their method, starting from simplest code snippets.
However I find that, Poltavsky's function works when we concretely specify a type parameter to 'loophole_t' class:
-----------------------------------good(clang++ -std=c++14)---------------------------------
using namespace std;
template <int N> struct tag {};
auto loophole(tag<0>);
template <typename T, int N> struct loophole_t {
friend auto loophole(tag<N>) { return T{}; };
};
void f_Poltavsky() {
/*https://alexpolt.github.io/type-loophole.html*/
sizeof(loophole_t<std::string, 0>);
cout << "Poltavsky:"
<< std::is_same<std::string, decltype(loophole(tag<0>{}))>::value
<< endl;
}
int main() {
f_Poltavsky();
return 0;
}
-----------------------------------good-----------------------------------------------
but never work when loophole_t is used inside a template function:
----------bad( error: function 'loophole' with deduced return type cannot be used before it is defined)-----------
using namespace std;
template <int N> struct tag {};
auto loophole(tag<1>);
template <typename T, int N> struct loophole_t {
friend auto loophole(tag<N>) { return T{}; };
};
template <typename T>/*cannot use auto in because of C++14*/
static void f1(T x) {
sizeof(loophole_t<T, 1>);
cout << std::is_same<T, decltype(loophole(tag<1>{}))>::value
<< endl;
}
int main() {
f1();
return 0;
}
-----------------------------------bad-----------------------------------------------
I cannot figure out what is preventing it to work. If templated f1() does not work, how could it work inside any templated converting operator?
With respect, Jinn
You need some "adl" to resolve that:
template <int N>
struct tag {
friend auto loophole(tag);
};
And make the call template dependent (to be called after instantiation of the template structure which define the function).
template <typename T, int N = 0>
static void f1(T) {
sizeof(loophole_t<T, N>);
std::cout << std::is_same<T, decltype(loophole(tag<N>{}))>::value << std::endl;
}