【问题标题】:How can we instantiate template functions with a reference type?我们如何用引用类型实例化模板函数?
【发布时间】:2018-01-09 04:33:35
【问题描述】:

C++ 不会使用 T = Hoge& 来实例化模板。

一个最小的例子:

  • hoge.h:

    #include<cstdio>
    class Hoge
    {
      public:
        Hoge()
          : hoge(0)
        {
        }
        ~Hoge()
        {
        }
    
        int hoge;
        void print() { printf("%d\n", hoge); }
    };
    
    template<typename T>
    void f(T a);
    
  • hoge.cpp:

    #include "hoge.h"
    template<typename T>
    void f(T a)
    {
      a.print();
    }
    
    template void f<Hoge &>(Hoge &a);
    
  • main.cpp:

    #include "hoge.h"
    int main(void)
    {
      Hoge h;
      f(h);
      return 0;
    }
    

我将这些编译为:g++ -std=c++11 main.cpp hoge.cpp。但它给出了一个链接器错误:

Undefined symbols for architecture x86_64:
  "void f<Hoge>(Hoge)", referenced from:
      _main in aa-e35088.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

接下来,我把main.cpp中的f(h)改成f&lt;Hoge &amp;&gt;,错误就消失了。

为什么在第一种情况下不调用f&lt;Hoge &amp;&gt;(Hoge &amp;)? 对于这种情况,我可以通过每次输入f&lt;Hoge &amp;&gt; 来避免错误。但是,当涉及到重载的运算符时,就无法做到。

请告诉我如何解决这个错误。

【问题讨论】:

    标签: c++ c++11


    【解决方案1】:

    编译器会尽量推导出最简单的模板T。这里T=Hoge 很好,所以编译器不会尝试更复杂的形式。

    不过,您可以清楚地说明您的意图。请尝试以下操作:

    template<typename T>
    void f(T& a);
    

    T 仍将被推导出为Hoge,但您的函数f 将获得引用。 这让读者可以直接在f原型中清楚地看到。

    当涉及到模板参数推导时,编译器引擎下会出现很多规则。当我声明编译器推断出最简单的 T 时,我真的是在偷工减料。这是一个可靠的来源:cppreference

    【讨论】:

      【解决方案2】:

      您可以像您所做的那样实例化具有引用类型的函数。但是,编译器不会 推断模板参数作为引用类型。您可以通过不让编译器推断参数而是指定参数来验证是否可以实例化函数模板:

      f<Hoge&>(h);
      

      如果你想获得一个引用类型推导,你需要使用一个转发引用作为你的函数模板的参数:

      template <typename T>
      void f(T&& a);
      

      当使用转发引用作为模板参数并传递Hoge参数时,根据参数的值类别推导参数:

      Hoge       h;
      Hoge const c;
      
      f(h);       // T becomes Hoge&
      f(c);       // T becomes Hoge const&
      f(Hoge());  // T becomes Hoge
      

      【讨论】:

      • @DietmarKühl 我确定您的意思是“不会将模板参数推断为引用类型”(除非使用转发引用)。
      • @M.M 实际上,在这种情况下,T 也变成了Hoge。与f(Hoge()) 中的相同。请注意,T 是模板参数的名称,而不是函数参数的类型 (T &amp;&amp;)。
      • @ArneVogel 好的。 This post 声称 T&amp;&amp; 推断为 xvalue 参数,但可能是错误的
      猜你喜欢
      • 2015-11-23
      • 1970-01-01
      • 2016-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-22
      • 1970-01-01
      相关资源
      最近更新 更多