提供适当的运营商<<具有可变参数模板专业化

时间:2015-05-12 13:15:19

标签: c++ templates operators friend

为模板类的特化提供operator<<时,clang喜欢内联的朋友形式:

#include <iostream>

template <typename A, typename... Bs>
struct Hello;

template <typename A>
struct Hello<A> {
  template <typename A2>
  friend std::ostream & operator<<(std::ostream & s, const Hello<A2> & h) {
    return s << "specialized\n";
  }
};

template <typename A, typename... Bs>
struct Hello {
  template <typename A2, typename... B2s>
  friend std::ostream & operator<<(std::ostream & s, const Hello<A2,B2s...> & h) {
    return s << "generic\n";
  }
};


int main()
{
  std::cout << Hello<int>() 
            << Hello<float>()
            << Hello<int,int>()
            << Hello<int,float>();
}

http://coliru.stacked-crooked.com/a/47743db96c0f3a02

然而gcc失败了,它更喜欢非内联版本:

#include <iostream>

template <typename A, typename... Bs>
struct Hello;

template <typename A>
struct Hello<A> {
  template <typename A2>
  friend std::ostream & operator<<(std::ostream & s, const Hello<A2> & h);
};

template <typename A, typename... Bs>
struct Hello {
  template <typename A2, typename... B2s>
  friend std::ostream & operator<<(std::ostream & s, const Hello<A2,B2s...> & h);
};


template <typename A2>
std::ostream & operator<<(std::ostream & s, const Hello<A2> & h) {
  return s << "specialized\n";
}

template <typename A2, typename... B2s>
std::ostream & operator<<(std::ostream & s, const Hello<A2,B2s...> & h) {
  return s << "generic\n";
}


int main()
{
  std::cout << Hello<int>() 
            << Hello<float>() 
            << Hello<int,int>() 
            << Hello<int,float>();
}

http://coliru.stacked-crooked.com/a/45328f7bbdb36598

反过来,clang不接受。

所以我的问题是:

  1. 两种形式都是标准C ++吗?
  2. 是否有两个编译器都接受的表单?

1 个答案:

答案 0 :(得分:2)

您不需要模板朋友。

template <typename A, typename... Bs>
struct Hello {
  friend std::ostream & operator<<(std::ostream & s, const Hello<A,Bs...> & h) {
    return s << "generic\n";
  }
};

template <typename A>
struct Hello<A> {
  friend std::ostream & operator<<(std::ostream & s, const Hello<A> & h) {
    return s << "specialized\n";
  }
};

http://coliru.stacked-crooked.com/a/22c439bc920f948c