花哨的黑客在本地而不是在在线编译器中打破反射

Fancy hack to get reflection breaking locally but not in online compiler

某位聪明人: https://www.youtube.com/watch?v=abdeAew3gmQ

想出了如何使用模板元编程来进行一些基本的反射。

好吧,我正在尝试将其与我的代码集成,但它导致了问题。

在在线编译器中这有效:

#include <iostream>
#include <tuple>
#include <iostream>
#include <array>
#include <utility>

using namespace std;

template <std::size_t I>
struct ubiq_constructor
{
    template <class Type>
    constexpr operator Type&() const noexcept;
};

template <class T, std::size_t I0, std::size_t... I>
constexpr auto detect_fields_count(std::size_t& out, std::index_sequence<I0, I...>)
    -> decltype( T{ ubiq_constructor<I0>{}, ubiq_constructor<I>{}... } )
{ out = sizeof...(I) + 1; }

template <class T, std::size_t... I>
constexpr void detect_fields_count(std::size_t& out, std::index_sequence<I...>) {
    detect_fields_count<T>(out, std::make_index_sequence<sizeof...(I) - 1>{});
}

struct POD {
    int f1;
    float f2;
    char h;
    char w;
};


int main()
{
    std::size_t size;
    detect_fields_count<POD>(size, std::make_index_sequence<sizeof(POD)>());
    cout << "size:" << size << endl;

    return 0;
}

输出:size:4

然而,当我把它放在一个更大的项目本地项目中时,它是用 gcc 编译的,我得到的似乎是 UB。我的程序提前终止,有时会遇到段错误,但有时甚至不会发生这种情况,我的代码只是停止,甚至 gdb 都不知道为什么。

我通过的所有测试,代码编译时只有一个警告(这是模板的一部分),如果我注释掉对它的任何调用,代码将正常运行,即

int example()
{
    cout << "AAAAAAAAAAAAAAAA: " << endl;
    std::size_t size = 0;
    detect_fields_count<POD>(size, std::make_index_sequence<sizeof(POD)>());
    cout << "size: " << size << endl;
    return 0;
}

在那个例子中,如果我注释掉 detect_fields_count 我的代码有效,否则,我可能会得到一个段错误,我可能会双重打印 "AAAAAAAAA" 然后得到一个段错误...

我不明白发生了什么,据我所知,模板化代码不应该破坏某些东西,但不知何故,即使我在我的代码中注释掉对其他函数的所有调用也是如此。我什至不知道从哪里开始调试这个。

问题是原始代码必须(出于我无法理解的原因)return 一个根据其签名的值,但它从来没有。

解决方案实际上是return防止段错误的东西:

template <class T, std::size_t I0, std::size_t... I>
constexpr auto detect_fields_count(std::size_t& out, std::index_sequence<I0, I...>)
    -> decltype( T{ ubiq_constructor<I0>{}, ubiq_constructor<I>{}... } )
{ out = sizeof...(I) + 1; return {}; }