Почему эти функции не превращаются в указатель на функцию? - PullRequest
1 голос
/ 17 июня 2020

У меня был класс, который содержал указатель на функцию, которая должна быть вызвана, и теперь я столкнулся с ситуацией, когда я хотел бы, чтобы эта вызываемая функция содержала автономную ссылку / значение (лямбда). Итак, я создаю свой шаблонный класс для приема либо указателей на функции, либо лямбда-выражений, например:

template <typename FunctionType>
class MyClass
{
public:
    MyClass(FunctionType function) : function(function) {}
    FunctionType function;
};

Однако кажется, что каждый раз, когда создается экземпляр этого класса, компилятор создает другой «тип» класса, как показано ниже:

int main()
{
    MyClass foo([]() {return 5; });
    MyClass foo2([]() {return 5; });
    MyClass foo3([]() {return 5; }); // ALL THREE OF THESE SEEM TO BE DIFFERENT TYPES
    MyClass foo4(static_cast<int(*)()> ([]() {return 5; })); // I THINK I CAN FORCE THEM TO BE THE SAME TYPES BY CASTING
    MyClass foo5(static_cast<int(*)()> ([]() {return 5; }));
    MyClass foo6(static_cast<int(*)()> ([]() {return 5; }));

    std::cout << typeid(foo).name() << '\n';
    std::cout << typeid(foo2).name() << '\n';
    std::cout << typeid(foo3).name() << '\n';
    std::cout << typeid(foo4).name() << '\n';
    std::cout << typeid(foo5).name() << '\n';
    std::cout << typeid(foo6).name() << '\n';
}

Результатом этого будет:

class MyClass<class <lambda_e39b14fd1b959adc3c33a259b5258211> >
class MyClass<class <lambda_de164f9f0bca248459ade49332a364c3> >
class MyClass<class <lambda_9fcf071b66983e924cb117ca1e77c4c6> >
class MyClass<int (__cdecl*)(void)>
class MyClass<int (__cdecl*)(void)>
class MyClass<int (__cdecl*)(void)>

Поскольку я буду создавать сотни или тысячи таких, я бы хотел, чтобы этого не было, если все возможно. Большинство функций, которые я передаю своему классу, должны быть одного и того же типа, за исключением случайных различных лямбд, которые мне понадобятся. Так неужели компилятор создает другой тип каждый раз, когда я передаю один и тот же тип функции? В таком случае это не кажется очень эффективным. Если это так, то как лучше всего сократить количество типов классов, создаваемых компилятором? Думаю, я добился этого, преобразовав указатель на функцию при создании класса, но это кажется ужасным способом сделать это.

1 Ответ

5 голосов
/ 17 июня 2020

Вместо этого вы можете заставить свой класс хранить указатель на функцию, например:

template <typename Ret, typename ...Args>
class MyClass
{
public:
    MyClass(Ret (*function)(Args...)) : function(function) {}
    Ret (*function)(Args...);
};

Затем вы можете сохранить лямбда, явно преобразовав ее в указатель функции:

MyClass foo( + []() {return 5; });

и тогда будет создан только один класс для каждой сигнатуры функции (будь то лямбда или функция).

Вот демо .

...