【问题标题】:How to speed up compilation of multiple template type definition? (macOS, Clang)如何加快编译多个模板类型定义? (macOS,Clang)
【发布时间】:2018-09-26 11:15:44
【问题描述】:

问题

我正在将 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)破坏。

问题

我想避免修复所有类,有没有办法,如何重写该定义以解决编译速度非常慢的问题?

【问题讨论】:

  • 编译时间不一定在您在此处显示的那一行,而更有可能在类的代码中。如果您不使用这些模板的实例化,它们将不会被编译,这将解释编译时间的极度下降。您在此处显示的内容并不能解释 60 分钟的编译...
  • 模板 B..E 看起来微不足道(除非有 很多 代码或您未显示的其他依赖项:构造函数本身并不复杂)。如果你只是make_shared&lt;ClassA&gt;(loader) 会发生什么? make_shared&lt;ClassB&lt;ClassA&gt;&gt;(loader) 呢?您应该能够看到减速发生的位置。

标签: c++ templates clang


【解决方案1】:

如果通过删除该模板代码行,您的代码仍然可以编译,那么这些模板构造函数可能不是必需的(您应该测试以确保)。但是由于存在这些构造函数时会增加编译时间,这意味着编译器需要这些模板的定义。

我认为这些模板构造函数在存在时会被调用,因为它们优先于特殊成员函数(甚至禁用默认构造函数的隐式定义):默认构造函数和复制/移动构造函数。

因此,如果您不想接触这些代码行,则可以声明默认的特殊构造函数,使其始终比这些模板更好地匹配复制和默认构造,或者可能更喜欢约束模板构造函数:

选项 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
};

【讨论】:

    猜你喜欢
    • 2017-06-19
    • 2012-11-29
    • 1970-01-01
    • 2015-10-23
    • 2019-04-28
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 2018-04-20
    相关资源
    最近更新 更多