Стирание типа с помощью указателей функций не работает с GCC - PullRequest
0 голосов
/ 05 декабря 2018

Я пытаюсь что-то вроде стирания типов с помощью некоторых указателей функций и шаблонов, как показано в примере ниже.Что я нахожу странным, так это то, что с GCC я получаю неправильный результат, тогда как с VS 2017 я получаю ожидаемый результат.Итак, кто прав, а кто неправ и почему?

Живой пример на COLIRU: http://coliru.stacked -crooked.com / a / 225db5711c07c8b0

struct A { void PrintA() { std::cout << "Event A" << std::endl; } };
struct B { void PrintB() { std::cout << "Event B" << std::endl; } };
struct C { void PrintC() { std::cout << "Event C" << std::endl; } };

struct RunBase
{
    virtual void operator()() = 0;
};


template <typename T>
struct Run : public RunBase
{
    using FUNC = void (T::*)();
    Run(T& o, FUNC&& f) : mObj(o), mFunc(f) {}
    void operator()() override { (mObj.*mFunc)(); }

    T& mObj;
    FUNC& mFunc;
};

int main()
{
    A a; 
    B b; 
    C c; 

    std::vector<std::unique_ptr<RunBase> > mFuncs;
    mFuncs.push_back(std::make_unique<Run<A> >(a, &A::PrintA));
    mFuncs.push_back(std::make_unique<Run<B> >(b, &B::PrintB));
    mFuncs.push_back(std::make_unique<Run<C> >(c, &C::PrintC));

    for (auto& i : mFuncs)
        (*i)();

  return 0;
}

Ожидаемый результат:

Event A
Event B
Event C

НоGCC дает мне:

Event C
Event C
Event C

1 Ответ

0 голосов
/ 05 декабря 2018

Это потому, что вы храните ссылку внутри вашего объекта, но &A::PrintA и т. Д. Являются временными файлами, которые уничтожаются в конце полного выражения, и поэтому ссылка на член остается висячей, и ее использование приводит к неопределенному поведению.

Просто сохраните копию указателя функции-члена, чтобы исправить это:

FUNC mFunc;

PS.Когда mFuncs уничтожается, уникальные указатели удаляют дочерние объекты через базовый указатель.Поведение не определено, если вы не объявите RunBase::~RunBase virtual.


Итак, кто прав, а кто неправ и почему?

Ваша программа неправильна;Для него нет правильного поведения.

...