【问题标题】:What does this "<>" mean inside a template class function?这个“<>”在模板类函数中是什么意思?
【发布时间】:2012-08-24 22:02:30
【问题描述】:

有这样的代码。

const std::string DeviceTypeStrings[] ={ "A", "B", "C", "D", "E" };

enum DeviceTypes { A = 0, B, C, D, E };

template <DeviceTypes T> class DeviceType;
template <DeviceTypes T> std::ostream& operator<< (std::ostream& output, const DeviceType<T>& dev);

template <DeviceTypes T> class DeviceType {
    public:
         static const int value = T;
         static const std::string string;
         friend std::ostream & operator<< <>(std::ostream & output, const DeviceType<T> & deviceType );
};
template <DeviceTypes T> const std::string DeviceType<T>::string = DeviceTypeStrings[T];
template <DeviceTypes T> std::ostream & operator<< (std::ostream & output, const DeviceType<T> & deviceType ){
    if ( DeviceType<T>::string.find(' ') != std::string::npos ){
        return output << "\"" << DeviceType<T>::string << "\""; 
    } else {
        return output << DeviceType<T>::string;
    }   
}

int main () {
    DeviceType<A> myType;
    std::cout << myType << std::endl;
    return 0;    
}

注意在DeviceType类的”,“”是什么意思?如果可以,为什么它必须在那里?

【问题讨论】:

  • 它可以编译吗?在我看来是个错误。
  • 它会编译。语法上是正确的。
  • @PeteBecker:- OP 是一个Negative Zero,所以一定已经编译了 ;)
  • 如果我把模板参数中的DeviceTypes改成classit compiles。我假设他有一个以 C++ 概念作为扩展的编译器?
  • 附上完全编译的代码。

标签: c++ templates


【解决方案1】:

这只是意味着友元声明是指 函数模板 operator &lt;&lt;(之前已声明)的特定特化,而不是一些尚未声明的普通非模板函数 operator &lt;&lt;

这个友元声明所指的特化是由参数推导机制决定的,即实际的模板参数是从友元声明中使用的参数类型隐式派生的。因此,无需在&lt;&gt; 中显式指定模板参数,但仍需要一对空的&lt;&gt;

换句话说,代码的作者本可以明确说明

friend std::ostream & operator<< <T>(std::ostream & output, 
                                     const DeviceType<T> & deviceType );

(注意&lt;T&gt; 中的显式T)。然而,由于编译器可以自己计算出来(从第二个参数的类型派生出来),所以完全可以只放一对空的&lt;&gt;

现在,如果代码刚刚说

friend std::ostream & operator<<(std::ostream & output, 
                                 const DeviceType<T> & deviceType );

(即根本没有&lt;&gt;),它会成为一个普通(非模板)函数operator &lt;&lt;,这不是作者想要的。

通过以下简单示例可以在没有任何朋友声明的情况下说明在此朋友声明中起作用的重载解析功能

void foo(int);
template <typename T> void foo(T);

int main() {
  foo(42);      // calls non-template function
  foo<int>(42); // calls template function, explicit template argument given
  foo<>(42);    // calls template function, template argument deduced by compiler
}

当你想告诉编译器你特别想引用函数的模板版本时,你必须在引用中包含三角括号,即使它们之间没有任何内容。

【讨论】:

  • 谢谢。我确实验证了如果我将 T 放在 中,代码会按预期工作。
【解决方案2】:

编译器在operator&lt;&lt; 之后检查&lt; 是否是模板类的友元函数。它被认为是模板参数列表。

【讨论】:

  • 我很确定 friend 与这里无关。实际上,如果没有friend,我无法复制这个问题,所以也许是这样。我很高兴我没有投反对票。
  • 你能告诉我为什么这是必要的吗?
  • @NegativeZero 当你指定你想要的输出类型时,它会指定类型如 , , 等,例如 operator(std stackoverflow.com/a/1789637/1381108
【解决方案3】:

link 也一样。 请参阅“模板专业化”一章。

// template specialization
#include <iostream>
using namespace std;

// class template:
template <class T>
class mycontainer {
    T element;
  public:
    mycontainer (T arg) {element=arg;}
    T increase () {return ++element;}
};

// class template specialization:
template <>
class mycontainer <char> {
    char element;
  public:
    mycontainer (char arg) {element=arg;}
    char uppercase ()
    {
      if ((element>='a')&&(element<='z'))
      element+='A'-'a';
      return element;
    }
};

int main () {
  mycontainer<int> myint (7);
  mycontainer<char> mychar ('j');
  cout << myint.increase() << endl;
  cout << mychar.uppercase() << endl;
  return 0;
}

这就是你引用已经定义的模板对象(或函数)的方式。

【讨论】:

    猜你喜欢
    • 2015-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-24
    • 2010-09-29
    • 1970-01-01
    • 2016-10-26
    • 1970-01-01
    相关资源
    最近更新 更多