SFINAE 重载 operator<< 以调用 'print' 方法(如果存在)
SFINAE overload operator<< to call 'print' method if it exists
我一直在努力理解 SFINAE,并试图编写一个简单的重载运算符 <<,它将在包含此类方法的任何 class 上调用 'print' 方法。我通读了问题 Is it possible to write a template to check for a function's existence? 的答案并尝试写:
template<class T, class = decltype(void(std::declval<T>().print), std::true_type{})>
inline std::ostream &operator<<(std::ostream &out, const T &obj) {
obj.print(out); return out; }
和
template<class T, class = decltype(void(std::declval<T>().print(std::declval<std::ostream &>())), std::true_type{})>
inline std::ostream &operator<<(std::ostream &out, const T &obj) {
obj.print(out); return out; }
但这根本行不通——编译器似乎没有问题为任何类型实例化模板,所以当我尝试打印诸如字符串文字之类的东西时会出现大量 'ambiguous overload' 错误...
您的"function exists"表达不正确。试试这个:
template <typename T,
typename = decltype(
void(std::declval<T>().print(std::declval<std::ostream&>())),
std::true_type{})> // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
std::ostream & operator<<(std::ostream & out, const T & obj)
{
obj.print(out);
return out;
}
您也可以考虑这个备选方案:
template <typename T>
auto operator<<(std::ostream & out, const T & obj)
-> decltype(obj.print(out), (void)0, out)
{
obj.print(out);
return out;
}
我不明白你的第二个类型参数是什么意思
class = decltype(void(std::declval<T>().print), std::true_type{})
的意思。这应该评估什么?
我认为您可以使用以下方法使其工作。
#include <iostream>
#include <type_traits>
template<typename T,
typename = decltype(std::declval<const T>().print(std::cout))>
std::ostream&
operator<<(std::ostream& out, const T& obj)
{
obj.print(out);
return out;
}
struct A
{
void
print(std::ostream& out) const
{
out << "A";
}
};
int
main()
{
A a {};
std::cout << "And the winner is: " << a << std::endl;
}
它会正确输出 And the winner is: A
但可能有一些我忽略的极端情况。
表达式
decltype(std::declval<const T>().print(std::cout))
将评估 return 类型的 print(std::ostream&) const
成员函数,如果声明了这样的函数,否则会出现类型错误。
我一直在努力理解 SFINAE,并试图编写一个简单的重载运算符 <<,它将在包含此类方法的任何 class 上调用 'print' 方法。我通读了问题 Is it possible to write a template to check for a function's existence? 的答案并尝试写:
template<class T, class = decltype(void(std::declval<T>().print), std::true_type{})>
inline std::ostream &operator<<(std::ostream &out, const T &obj) {
obj.print(out); return out; }
和
template<class T, class = decltype(void(std::declval<T>().print(std::declval<std::ostream &>())), std::true_type{})>
inline std::ostream &operator<<(std::ostream &out, const T &obj) {
obj.print(out); return out; }
但这根本行不通——编译器似乎没有问题为任何类型实例化模板,所以当我尝试打印诸如字符串文字之类的东西时会出现大量 'ambiguous overload' 错误...
您的"function exists"表达不正确。试试这个:
template <typename T,
typename = decltype(
void(std::declval<T>().print(std::declval<std::ostream&>())),
std::true_type{})> // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
std::ostream & operator<<(std::ostream & out, const T & obj)
{
obj.print(out);
return out;
}
您也可以考虑这个备选方案:
template <typename T>
auto operator<<(std::ostream & out, const T & obj)
-> decltype(obj.print(out), (void)0, out)
{
obj.print(out);
return out;
}
我不明白你的第二个类型参数是什么意思
class = decltype(void(std::declval<T>().print), std::true_type{})
的意思。这应该评估什么?
我认为您可以使用以下方法使其工作。
#include <iostream>
#include <type_traits>
template<typename T,
typename = decltype(std::declval<const T>().print(std::cout))>
std::ostream&
operator<<(std::ostream& out, const T& obj)
{
obj.print(out);
return out;
}
struct A
{
void
print(std::ostream& out) const
{
out << "A";
}
};
int
main()
{
A a {};
std::cout << "And the winner is: " << a << std::endl;
}
它会正确输出 And the winner is: A
但可能有一些我忽略的极端情况。
表达式
decltype(std::declval<const T>().print(std::cout))
将评估 return 类型的 print(std::ostream&) const
成员函数,如果声明了这样的函数,否则会出现类型错误。