假设我具有以下元功能:

template <typename T>
struct make_pair {
    using type = std::pair<
        typename std::remove_reference<T>::type,
        typename std::remove_reference<T>::type
    >;
};

这样做会提高编译速度吗?
template <typename T>
struct make_pair {
    using without_reference = typename std::remove_reference<T>::type;
    using type = std::pair<without_reference, without_reference>;
};

我看到两种可能性:
  • 每次看到typename std::remove_reference<T>::type时,编译器都必须做一些工作。使用中间别名具有某种“缓存”行为,这使编译器只能执行一次工作。
  • 编译时性能是根据编译器必须执行的模板实例化数量来衡量的。由于std::remove_reference<T>::type的类型与std::remove_reference<T>::type相同,因此在两种情况下都只需要一个模板实例化,因此这两种实现都具有等效的WRT编译时性能。

  • 我认为B是正确的,但我想确定。如果答案是特定于编译器的,我将最有兴趣了解Clang和GCC的答案。

    编辑:

    我对测试程序的编译进行了基准测试,以使用一些数据。测试程序会执行以下操作:
    template <typename ...> struct result;
    
    template <typename T>
    struct with_cache {
        using without_reference = typename std::remove_reference<T>::type;
        using type = result<without_reference, ..., without_reference>;
    };
    
    template <typename T>
    struct without_cache {
        using type = result<
            typename std::remove_reference<T>::type,
            ...,
            typename std::remove_reference<T>::type
        >;
    { };
    
    using Result = with[out]_cache<int>::type;
    

    这些是该程序进行10次编译的平均时间,在result<>中具有10000个模板参数。
                    -------------------------
                    | g++ 4.8 | clang++ 3.2 |
    -----------------------------------------
    | with cache    | 0.1628s | 0.3036s     |
    -----------------------------------------
    | without cache | 0.1573s | 0.3785s     |
    -----------------------------------------
    

    该测试程序由可用的脚本here生成。

    最佳答案

    我不能说所有编译器都是如此,但是GCC以及很可能其他主要编译器都将使用备忘录。如果您考虑一下,它几乎是必须的。

    考虑以下代码

    &f<X, Y>::some_value == &f<X, Y>::some_value
    

    这必须是正确的,因此编译器必须确保它不重复方法和静态成员的定义。现在可能还有其他方法可以执行此操作,但这只是给我留下了记忆。我什至看不到另一种实现此方法的方法(当然,我已经非常努力地考虑过)

    当我使用TMP时,我希望会发生内存。如果没有,那就太痛苦了,太慢了。我看到编译时间性能的主要差异的唯一方法是:a)使用更快的编译器(如Clang(比GCC快3倍))并选择不同的算法。在我看来,小的恒定因素在TMP中的重要性甚至不如C或C++。选择正确的算法,尽量不要做不必要的工作,尽量减少实例化的数量,并使用良好的编译器(MSVC++确实很慢,并且与C++ 11的兼容性相差甚远,但GCC和Clang相当不错);这就是您真正能做的。

    同样,您应该始终牺牲编译时间以获得更好的代码。与普通的过早优化相比,过早的编译时间优化的危害更大。如果由于某种原因性能变得严重阻碍了开发,则可能会有异常(exception)。但是,我从未听说过这种情况。

    关于c++ - 通过缓存元函数来优化编译时性能,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17203558/

    10-11 22:47
    查看更多