提供适当的 operator<< 和可变模板特化
Provide a proper operator<< with variadic template specialization
当为模板class的专业化提供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 接受。
所以我的问题是:
- 这两种形式都是标准的 C++ 吗?
- 是否有两种编译器都接受的形式?
你不需要模板朋友。
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";
}
};
当为模板class的专业化提供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 接受。
所以我的问题是:
- 这两种形式都是标准的 C++ 吗?
- 是否有两种编译器都接受的形式?
你不需要模板朋友。
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";
}
};