Использование `extern template` со сторонней библиотекой только для заголовков - PullRequest
6 голосов
/ 28 апреля 2020

Я использую библиотеку glm , которая представляет собой набор математических утилит, предназначенных только для заголовков, предназначенных для трехмерной графики. Используя -ftime-trace в Clang и ClangBuildAnalyzer, я заметил, что много времени тратится на создание экземпляров glm типов:

**** Templates that took longest to instantiate:
 16872 ms: glm::vec<4, signed char, glm::packed_highp> (78 times, avg 216 ms)
 15675 ms: glm::vec<4, unsigned char, glm::packed_highp> (78 times, avg 200 ms)
 15578 ms: glm::vec<4, float, glm::packed_highp> (78 times, avg 199 ms)

...

Итак, Я решил создать заголовок / исходную пару оболочки для glm и использовать extern template, чтобы избежать ненужных реализаций:

// glmwrapper.h

#pragma once

#include <glm.hpp>

extern template struct glm::vec<4, signed char, glm::packed_highp>;
extern template struct glm::vec<4, unsigned char, glm::packed_highp>;
extern template struct glm::vec<4, float, glm::packed_highp>;
// glmwrapper.cpp

template struct glm::vec<4, signed char, glm::packed_highp>;
template struct glm::vec<4, unsigned char, glm::packed_highp>;
template struct glm::vec<4, float, glm::packed_highp>;

Теперь в моем проекте вместо включения <glm.hpp>, Я включаю "glmwrapper.h" вместо этого. К сожалению, это ничего не изменило. Использование -ftime-trace и ClangBuildAnalyzer снова сообщает о том же количестве экземпляров. Также нет измеримой разницы во времени компиляции.

I подозревают , что это потому, что #include <glm.hpp> действительно заканчивается включением определения шаблона, и в этот момент последующие объявления extern template просто избыточно.

Есть ли способ достичь того, что я хочу, без изменения библиотеки glm?


В псевдокоде я хочу что-то вроде этого:

// glmwrapper.h (psuedocode)

#pragma once

#include <glm.hpp>

// Make definition of the templates unavailable:
undefine template struct glm::vec<4, signed char, glm::packed_highp>;
undefine template struct glm::vec<4, unsigned char, glm::packed_highp>;
undefine template struct glm::vec<4, float, glm::packed_highp>;

// Make declaration of the templates available:
extern template struct glm::vec<4, signed char, glm::packed_highp>;
extern template struct glm::vec<4, unsigned char, glm::packed_highp>;
extern template struct glm::vec<4, float, glm::packed_highp>;
// glmwrapper.cpp (psuedocode)

// Define templates only in the `.cpp`, not in the header:
template struct glm::vec<4, signed char, glm::packed_highp>;
template struct glm::vec<4, unsigned char, glm::packed_highp>;
template struct glm::vec<4, float, glm::packed_highp>;

1 Ответ

0 голосов
/ 03 мая 2020

Если ваше подозрение верно и библиотека по какой-то причине создает экземпляры этих шаблонов еще до того, как ваш extern template даже будет рассмотрен, тогда как насчет изменения порядка вещей?

// glmwrapper.h

#pragma once

// This include forward declares the vec template
#include <glm/detail/qualifier.hpp>

extern template struct glm::vec<4, signed char, glm::packed_highp>;
extern template struct glm::vec<4, unsigned char, glm::packed_highp>;
extern template struct glm::vec<4, float, glm::packed_highp>;

#include <glm.hpp>
...