【发布时间】:2013-06-16 17:09:14
【问题描述】:
假设我有以下元函数:
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<> 中有 10 000 个模板参数。
-------------------------
| g++ 4.8 | clang++ 3.2 |
-----------------------------------------
| with cache | 0.1628s | 0.3036s |
-----------------------------------------
| without cache | 0.1573s | 0.3785s |
-----------------------------------------
测试程序由here可用的脚本生成。
【问题讨论】:
-
我认为任何猜测都无法取代实际测量。请发布一些时序图,然后我们可以创建一个很好的理论来解释它们。
-
我看到一个关于 clang 的演讲,说他们为模板实例化而不是链接列表制作哈希表。不过我不知道他们是在和谁比较。
-
一个不做记忆的
template编译器将会非常慢。 -
@Yakk:另一方面,我看到 gcc 在某些输入上崩溃,因为它缓存了太多以至于超出了可用内存,而 clang 非常慢,但至少编译了野兽(当然,我说的是荒谬的输入:p)。
标签: c++ templates instantiation template-meta-programming boost-mpl