如何显式调用运算符 << 的模板化重载?
How to explicity call a templated overload of operator <<?
考虑以下为 class A
重载 operator<<
的示例代码:
#include <iostream>
class A {
template <typename T>
friend A &operator<<(A &a, const T &t)
{
std::cout << t << std::endl;
return a;
}
friend A &operator<<(A &a, const std::string &t)
{
return operator<<<std::string>(a, t + "x");
}
};
我的意图是第二个运算符显式调用第一个运算符。
然而,在 g++ 7.4 中,这失败了
In function 'A& operator<<(A&, const string&)':
error: 'operator<<' not defined
return operator<<<std::string>(a, t + "x");
^~
error: expected primary-expression before '>' token
return operator<<<std::string>(a, t + "x");
^
但是我不明白为什么这不应该编译。
调用函数而不是调用运算符。
#include <iostream>
class A {
template <typename T>
static A &print(A &a, const T &t)
{
std::cout << t << std::endl;
return a;
}
template <typename T>
friend A &operator<<(A &a, const T &t)
{
return print(a, t);
}
friend A &operator<<(A &a, const std::string &t)
{
return print(a, t + "x");
}
};
In-class 友元函数不 暴露给任何作用域。朋友注入曾经是一回事(在发明 ADL 之前),但现在除了使用 ADL 之外没有其他方法可以调用它们,除非您事先声明它们。在这种情况下,解决方法是事先在 class 之外声明模板函数。
class A;
template <typename T>
A &operator<<(A &a, const T &t);
您似乎希望 specialize your template function,但您做的并不完全正确。它应该看起来更像这样:
template <> friend A& operator<< <std::string>(A &a, const std::string &t)
{
// Print in here some how. It's not exactly clear to me how you intend to
// do this, as doing something like a << t will create infinite recursion
// finally, return a
return a;
}
您的另一个选择是切换函数的顺序,在您创建第一个函数之后创建模板函数:
friend A &operator<<(A &a, const std::string &t)
{
// Again, still not sure what you want to do here
// I just want to stress again though, don't do something
// like a << t, or operator<<(a,t)
// That will crash hard and fast, as there is no way to resolve
// it. It will create infinite recursion
return a;
}
template <typename T>
friend A &operator<<(A &a, const T &t)
{
std::cout << t << std::endl;
return a;
}
My intention is that the second operator explicitly calls the first one.
因此,首先,在这种情况下,您需要实际需要第一个选项。
其次,为此,您需要为 t
选择一种类型。你会这样做:
operator<< <SomeType>(a,t);
请记住,t
需要 implicitly converted 到 SomeType
。否则,SomeType
需要通过调用其构造函数来创建:
operator<< <SomeType>(a,SomeType(/* parameters to construct a SomeType ... */));
注意:像operator<< <SomeType>(a,t + "x")
这样的操作总是会变成infinitely recursive, and ultimately crash. This is because t + "x"
is always an std::string
. That means the compiler will always call this overload of the function infinitely, until it finally crashes from a stack overflow。所以不要那样做。
考虑以下为 class A
重载 operator<<
的示例代码:
#include <iostream>
class A {
template <typename T>
friend A &operator<<(A &a, const T &t)
{
std::cout << t << std::endl;
return a;
}
friend A &operator<<(A &a, const std::string &t)
{
return operator<<<std::string>(a, t + "x");
}
};
我的意图是第二个运算符显式调用第一个运算符。
然而,在 g++ 7.4 中,这失败了
In function 'A& operator<<(A&, const string&)':
error: 'operator<<' not defined
return operator<<<std::string>(a, t + "x");
^~
error: expected primary-expression before '>' token
return operator<<<std::string>(a, t + "x");
^
但是我不明白为什么这不应该编译。
调用函数而不是调用运算符。
#include <iostream>
class A {
template <typename T>
static A &print(A &a, const T &t)
{
std::cout << t << std::endl;
return a;
}
template <typename T>
friend A &operator<<(A &a, const T &t)
{
return print(a, t);
}
friend A &operator<<(A &a, const std::string &t)
{
return print(a, t + "x");
}
};
In-class 友元函数不 暴露给任何作用域。朋友注入曾经是一回事(在发明 ADL 之前),但现在除了使用 ADL 之外没有其他方法可以调用它们,除非您事先声明它们。在这种情况下,解决方法是事先在 class 之外声明模板函数。
class A;
template <typename T>
A &operator<<(A &a, const T &t);
您似乎希望 specialize your template function,但您做的并不完全正确。它应该看起来更像这样:
template <> friend A& operator<< <std::string>(A &a, const std::string &t)
{
// Print in here some how. It's not exactly clear to me how you intend to
// do this, as doing something like a << t will create infinite recursion
// finally, return a
return a;
}
您的另一个选择是切换函数的顺序,在您创建第一个函数之后创建模板函数:
friend A &operator<<(A &a, const std::string &t)
{
// Again, still not sure what you want to do here
// I just want to stress again though, don't do something
// like a << t, or operator<<(a,t)
// That will crash hard and fast, as there is no way to resolve
// it. It will create infinite recursion
return a;
}
template <typename T>
friend A &operator<<(A &a, const T &t)
{
std::cout << t << std::endl;
return a;
}
My intention is that the second operator explicitly calls the first one.
因此,首先,在这种情况下,您需要实际需要第一个选项。
其次,为此,您需要为 t
选择一种类型。你会这样做:
operator<< <SomeType>(a,t);
请记住,t
需要 implicitly converted 到 SomeType
。否则,SomeType
需要通过调用其构造函数来创建:
operator<< <SomeType>(a,SomeType(/* parameters to construct a SomeType ... */));
注意:像operator<< <SomeType>(a,t + "x")
这样的操作总是会变成infinitely recursive, and ultimately crash. This is because t + "x"
is always an std::string
. That means the compiler will always call this overload of the function infinitely, until it finally crashes from a stack overflow。所以不要那样做。