Как ускорить компиляцию нескольких определений типов шаблонов?(macOS, Clang) - PullRequest
0 голосов
/ 26 сентября 2018

Проблема

Я портирую библиотеку C ++ на macOS (с компилятором Clang ).Кажется, он зависает в какой-то момент, и задерживает время компиляции до 60+ минут .После выделения проблемы, которую я выяснил, она вызвана этим определением шаблона монстра (заменены имена классов) :

auto table = std::make_shared<ClassE<ClassD<ClassC<ClassB<ClassA>>>>(loader);

Все классы являются шаблонами и содержат конструктор (кроме ClassA) похож на это:

template<typename T> class ClassB: public T {
public:
    template<typename...ARGS> ClassB(ARGS&&...args):T(args...){}
    //...
};

Когда я удаляю эту строку кода шаблона, он обычно компилируется за несколько секунд.Он отлично работает на платформах Windows (Visual Studio) и Linux, поэтому, вероятно, он поврежден компилятором macOS (XCode, Apple LLVM, Clang).классы, есть ли способ, как переписать это определение для решения действительно медленной компиляции?

1 Ответ

0 голосов
/ 26 сентября 2018

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

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

Так что, если вы не хотите трогать эти строки кода, вы можете объявить специальные конструкторы по умолчанию таким образом, чтобы они всегда были лучшесоответствуют этим шаблонам для копирования и построения по умолчанию или могут предпочитать ограничивать конструкторы шаблонов:

Опция 1 :

template<typename T> class ClassB: public T {
public:
    ClassB() =default;
    ClassB(const ClassB&) =default;
    ClassB(ClassB&&) =default;
    ClassB(ClassB&) =default; //also, to be a better match
    ClassB(const ClassB&&) =default; //idem

    template<typename...ARGS> ClassB(ARGS&&...args):T(args...){}
    //...don't have to worry any more if you declare another
    //...template constructor
};

Опция 2 :

template<typename T> class ClassB: public T {
public:

    template<typename Arg,typename...ARGS,
      class=std::enable_if_t<!std::is_same_v<std::decay_t<Arg>,ClassB>>>
    ClassB(Arg&& arg,ARGS&&...args):T(arg,args...){}
    //... You should apply this constrain to all template
    //...  constructors that have a similar signature
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...