Общие лямбда-выражения и размер двоичного кода/раздувание кода

Какая разница в результирующем бинарнике, когда мы сравниваем этот код:

struct S {
    template<typename... Args>
    void operator()(Args... args) { /* ... */ }
};

// And then inside some block:
S s;
s(42);
s(3.14, "Hi!");
s("Hi!", 3.14);

...в этот код:

const auto l = [](auto... args) { /* ... */ };

// And then inside some block:
l(42);
l(3.14, "Hi!");
l("Hi!", 3.14);

Насколько я понимаю, код struct создает 3 экземпляра шаблона для operator(), все из которых отображаются как символы в двоичном коде. Что с лямбдой? Компилятор создает объект, похожий на s. Но если это тип безымянного класса, создает ли он символы в двоичном коде?

Мотивация: я использовал библиотеку с большим количеством шаблонов, в которой мне нужно было включить /bigobj. Я хотел бы избежать этого, и мне интересно, могут ли лямбда-выражения помочь против раздувания кода шаблона. Определено ли это в стандарте или зависит от реализации компилятора?


person basteln    schedule 12.09.2018    source источник
comment
В этом случае действительно помогло бы встраивание, удалив символы для лямбда-выражений.   -  person Guillaume Racicot    schedule 13.09.2018
comment
Попробуйте поместить структуру в безымянное пространство имен.   -  person Kerrek SB    schedule 13.09.2018
comment
Посмотрите на вывод вашего компилятора и найдите свою настоящую проблему. Шаблоны и т. д. — это синтаксический сахар. Раздувание кода сейчас не так актуально, как 20 лет назад, а затраты на хранение гораздо меньше, чем время разработчиков. Какова ваша настоящая цель здесь? Ваши примеры делают то же самое. Если он компилируется, это потому, что компилятор будет генерировать разные версии для auto, как и для шаблонов. auto не поддерживает динамическую типизацию. Это по-прежнему статически типизированный язык, и вам нужны разные версии для разных типов. Шаблоны, прочая магия компилятора - не имеет значения.   -  person 3Dave    schedule 13.09.2018
comment
Я бы предположил, что последний пример даже не компилируется, потому что аргументы имеют разные типы в разных вызовах?   -  person crazypeter    schedule 13.09.2018
comment
@crazypeter Это особенность общих лямбда-выражений.   -  person François Andrieux    schedule 13.09.2018
comment
@3Dave Как я уже писал, моя настоящая цель — избегать /bigobj. Можете ли вы дать мне ссылку, чтобы доказать, что вывод компилятора (за исключением, может быть, имен символов) точно такой же в двух примерах? Мой вопрос: поскольку лямбда создает безымянный тип класса, создает ли он символы в двоичном коде?   -  person basteln    schedule 13.09.2018


Ответы (1)


Я думаю, к сожалению, лямбда не может помочь вам решить проблему раздувания кода. Для вашего примера, как и для структуры S, компилятор также создаст три разных оператора () для лямбда.

Чтобы доказать свою точку зрения, я скомпилировал следующую программу с помощью g++ 8.1.0 в Linux.

int main()
{
    const auto l = [](auto... args) { /* ... */ };
    l(42);
    l(3.14, "Hi!");
    l("Hi!", 3.14);
}

а затем используйте команду nm для просмотра двоичного файла, результат будет следующим:

вывод команды nm

Нетрудно заметить, что последние три строки являются символами оператора тройки (). Итак, в данном случае lambda и struct S принципиально не отличаются.

person eprom    schedule 13.09.2018
comment
Спасибо! Хорошо знать. - person basteln; 13.09.2018