我一直试图了解SFINAE,并试图编写一个简单的重载运算符<<这将打电话给'打印'包含这种方法的任何类的方法。我仔细阅读了问题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; }
但这根本不起作用 - 编译器似乎没有问题为任何类型实例化模板,因此给出了一些模糊的过载&#39;当我尝试打印像字符串文字这样的东西时出错......
答案 0 :(得分:1)
您的“功能存在”表达式不正确。试试这个:
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;
}
答案 1 :(得分:0)
我不明白你的第二种类型参数
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))
如果声明了这样的函数,将评估print(std::ostream&) const
成员函数的返回类型,否则将返回类型错误。