C ++ 11 — Решения полиморфизма времени компиляции

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

«Обычный» способ сделать это в C ++ — это загрязнить код большим количеством #ifdef при написании метода или класса.

Проблема с подходом заключается в том, что:

  • исходный код выглядит действительно некрасиво
  • если вы поддерживаете 3 платформы, ваш исходный код примерно в 3 раза больше того, что вам действительно нужно, а это означает, что вашему компилятору все еще нужно проанализировать и проанализировать весь код, чтобы «увидеть» #ifdef
  • нет реальных различий между различными реализациями, трудно поддерживать, когда база кода растет, а когда у вас просто 3-4 платформы, она растет очень быстро.

Поскольку в C ++ 11 появилось много новых функций, мне было интересно, если что-то изменилось и есть ли новые опции для этого.

4

Решение

Вы должны использовать свою систему сборки для этого. Вы должны предоставить заголовкам независимые от платформы объявления функций и определений классов. Затем, в зависимости от целевой платформы, система сборки должна скомпилировать соответствующие реализации этих функций и классов.

Например, давайте рассмотрим создание окон для отображения графики или элементов графического интерфейса. Если вы не используете библиотеку для этого, вы должны написать кросс-платформенный код самостоятельно. Во-первых, вы должны подумать о том, каким должен быть независимый от платформы интерфейс. Возможно, у вас есть window класс и некоторые вспомогательные функции. Затем вы можете предоставить определение для этого класса и объявления вспомогательных функций в заголовочном файле и предоставить отдельные реализации для каждой платформы. Тогда у вас будет набор таких файлов:

  • window.h
  • window_wayland.cpp
  • window_winapi.cpp
  • window_x11.cpp

Теперь все файлы, которые должны использовать ваш класс и функции, должны просто #include <window.h>, Все они получают одинаковые объявления функций. Однако вы указываете в конфигурации вашей системы сборки, что window_x11.cpp должны быть скомпилированы в системах с оконной системой X11, window_wayland.cpp в системах с Wayland, и window_winapi на винде. Это означает, что в зависимости от платформы, на которой вы строите, вы получите реализацию этого заголовка, которая работает на целевой платформе.

Это имеет несколько хороших преимуществ:

  1. Вы разделили проблемы сборки (для какой платформы вы строите) и проблемы кода.
  2. Каждая зависящая от платформы реализация имеет свой собственный файл.
  3. У вас нет файла, загроможденного директивами препроцессора, и трудно следовать путям выполнения.

Это не означает, что в использовании определений для выборочной компиляции различных частей вашего кода нет ничего плохого. Я предпочитаю видеть это только с небольшим количеством кода, который был локализован в зависимых от платформы частях. В идеале, обернуть зависимый от платформы код в функцию и иметь #ifdefпросто поменять реализацию.

Как именно вы делаете это выборочное построение, зависит от используемой вами системы сборки. Для системы сборки GNU вы можете добиться условной компиляции с помощью automake. Некоторые примеры приведены в документации. Простой приведенный пример:

bin_PROGRAMS = hello
if LINUX
hello_SOURCES = hello-linux.c hello-common.c
else
hello_SOURCES = hello-generic.c hello-common.c
endif

Бег automake с этой конфигурацией сгенерирует соответствующий make-файл.

6

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector