【问题标题】:Are there compiler optimisations for methods of a templated class that don't use the template parameter?对于不使用模板参数的模板类的方法,是否有编译器优化?
【发布时间】:2017-03-10 09:32:10
【问题描述】:

例如

template< class T >
class Foo
{
public:
    float MethodUseOfT()
    {
        return m_bar.CalculateSomething();
    }
    float MethodNoUseOfT()
    {
        float blah(0.f);
        ...
        return blah;
    }

private:
    T m_bar;
};

class Bar
{
public:
    float CalculateSomething();
}

如果有人创建了Foo&lt;Bar&gt;,大多数编译器是如何管理的;例如,他们是否会普遍意识到MethodNoUseOfT 没有引用模板参数并使用该信息来减少生成的机器代码的大小?

另外,如果MethodUseOfT 的内容很大并且只有一行引用T,编译器会再次尝试重用为该方法的其余部分生成的机器代码吗?

【问题讨论】:

  • 我没有看到MethodUseOfT 实际上使用 T?或者一般使用T
  • 至于您的问题,现代编译器在优化方面通常非常出色。但唯一确定的方法是实际检查生成的代码。
  • 编辑:谢谢。抱歉,m_bar 现在是 T 类型。

标签: c++ templates compiler-optimization


【解决方案1】:

也许吧。

Microsoft C++ 可以选择合并相同的函数(当然Foo&lt;int&gt;::MethodNoUseOfT() 将与Foo&lt;double&gt;::MethodNoUseOfT() 相同)。

通常,此选项不符合标准(因为从函数模板生成的两个普通函数需要具有不同的地址,即使它们在其他方面相同)。然而这在这种情况下并不适用,因为没有办法获得成员函数的地址(指向成员函数的指针与地址非常不同,并且比地址复杂得多) - 所以链接器或许能做到。

如 cmets 中所述,唯一确定的方法是检查编译器+链接器的输出。

确定的简单方法是编写如下内容:

class FooBase
{
public:
    float MethodNoUseOfT()
    {
        float blah(0.f);
        ...
        return blah;
    }
};

template< class T >
class Foo : public FooBase
{
public:
    float MethodUseOfT()
    {
        return m_bar.CalculateSomething();
    }

private:
    T m_bar;
};

class Bar
{
public:
    float CalculateSomething();
}

如果您这样做,您甚至可以将 MethodNoUseOfT 的实现移动到 CPP 文件中。

【讨论】:

    【解决方案2】:

    仅在内联时;否则,由于符号被破坏,它们必须是单独的机器代码块。

    【讨论】:

    • 请注意,模板成员函数几乎必须内联,除非您使用显式实例化。
    【解决方案3】:

    视情况而定。

    重要的部分是 14.7.1 隐式实例化。 “当在需要函数定义存在的上下文中引用特化时,函数模板特化被隐式实例化。”

    换句话说,您认为的“优化”实际上是隐式实例化的强制行为。对于显式实例化,编译器将编译所有成员(毕竟,这是显式实例化的重点)。不过,链接器仍然可以消除未使用的函数。

    没有编译器会尝试重用模板方法的一半。这将需要极其复杂的分析,这将浪费在生成代码中节省的任何时间。

    【讨论】:

      猜你喜欢
      • 2010-10-09
      • 1970-01-01
      • 1970-01-01
      • 2011-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-25
      相关资源
      最近更新 更多