【问题标题】:How smart are C++ compilers about code size with template classes?C++ 编译器对模板类的代码大小有多聪明?
【发布时间】:2021-01-08 00:46:12
【问题描述】:

考虑以下代码:

template<typename T, size_t S> struct MyArray {
  int length;
  T contents_[S];

  MyArray() { length = S; }

  T& operator[](const int index) {
    assert(index >= 0 && index < length);
    return contents_[index];
  }

  int Length() { return length; }

};

从根本上说,没有理由为 S 的每个值创建 Length 函数和下标运算符的单独副本。但我担心实际上每个不同的 S 值都会重复这些函数,从而限制这种方法的用处。

(如果你好奇我为什么不使用 std::vector,那是因为这是一个没有任何基于堆的内存分配的嵌入式应用程序)

【问题讨论】:

  • std::array
  • Length() 是否仍等于 Slength 会员有用吗?
  • 另外,为了记录,创建下标运算符的单独副本的原因。 contents_[index] 的实现方式因contents_ 的类型而异(索引算法不同;它取决于底层类型的大小。你不能用一个函数实现来完成所有数组索引)。
  • 另外,Length() 可能最终没有代码,无论模板如何。生成的字节码几乎可以肯定只是直接访问length 成员。但是对于更复杂的方法,您的问题会成立。
  • godbolt 中玩了一会儿,似乎(1)在低优化级别,没有进行合并,(2)在高优化级别,无论如何,一切都是微不足道的内联。假设您担心空间问题并启用了优化,那么您似乎没有什么可担心的。

标签: c++ templates code-size


【解决方案1】:

MSVC 使用“相同的 comdat 折叠”(ICF)。这需要任何两个具有相同实现的方法(或函数)......并为它们使用相同的函数。

gcc 的黄金链接器(显然还有 clang)也可以做到这一点(具有不同程度的攻击性)。

除此之外,您必须手动完成。

struct baseArray{
  int length=0;
  int Length() const { return length; }
};
template<class T>
struct buffBaseArray:baseArray{
  T& operator[](const int index) {
    assert(index >= 0 && index < this->length);
    return reinterpret_cast<T*>(this+1)[index];// todo// alignment and ub
  }
};
  
template<typename T, size_t S>
struct MyArray:buffBaseArray<T> {
  T contents_[S];
  MyArray() { length = S; }
 };

或更少的 UB。

【讨论】:

  • 你说的“而且很明显”是什么意思
  • @passer 我知道它是一个 gcc 链接器;我用谷歌搜索它可以与clang一起使用,但只是现在。
  • 哦。我以为你的意思可能是 lld。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-14
  • 1970-01-01
  • 2017-02-01
相关资源
最近更新 更多