假设我具有以下元功能:
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/