C++ 有没有办法确定类是否有重载运算符?
我正在编写一个模板类,其中需要一个方法将元素类打印到stdout中。但是我在编写它时遇到了一个问题-如果cout如果操作符没有重载,那么您的程序就无法编译。这是一个编译时错误,无法将其延迟到运行时 一种解决方法是不使用运算符,而是使用函数指针。如果不支持该操作,则可以将函数指针设置为0,您可以在运行时检测该指针C++ 有没有办法确定类是否有重载运算符?,c++,class,overloading,C++,Class,Overloading,我正在编写一个模板类,其中需要一个方法将元素类打印到stdout中。但是我在编写它时遇到了一个问题-如果cout如果操作符没有重载,那么您的程序就无法编译。这是一个编译时错误,无法将其延迟到运行时 一种解决方法是不使用运算符,而是使用函数指针。如果不支持该操作,则可以将函数指针设置为0,您可以在运行时检测该指针 class A { public: int q; // some data typedef std::function<void(std::ostream&
class A {
public:
int q; // some data
typedef std::function<void(std::ostream& os, const A&)> PrinterFunc;
PrinterFunc func;
friend std::ostream& operator<<(std::ostream& os, const A& a) {
if(!a.func) {
throw "Not supported";
}
func(os,a);
return os;
}
};
A a;
a.func = [](std::ostream& os, const A& a) { os << "hello " << a.q; }
std::cout << a << std::endl; // will print
A b;
std::cout << b << std::endl; // will throw
本例使用C++11和。对于C++03,您必须使用普通函数指针。您可以使用一些SFINAE来测试是否存在格式化的输出运算符:
#include <iostream>
// HasFormattedOutput
// ============================================================================
namespace HasFormattedOutput {
namespace Detail
{
struct Failure{};
}
template<typename OutputStream, typename T>
Detail::Failure operator << (OutputStream&, const T&);
template<typename OutputStream, typename T>
struct Result : std::integral_constant<
bool,
! std::is_same<
decltype(std::declval<OutputStream&>() << std::declval<T>()),
Detail::Failure
>::value
> {};
} // namespace HasFormattedOutput
template <typename T, typename OutputStream = std::ostream>
struct has_formatted_output : std::conditional<
HasFormattedOutput::Result<OutputStream, T>::value,
std::true_type,
std::false_type>::type
{};
// Test
// ============================================================================
struct X {};
int main() {
std::cout.setf(std::ios_base::boolalpha);
std::cout << has_formatted_output<const char*>() << '\n';
std::cout << has_formatted_output<X>() << '\n';
}
C++11与编译错误相比,您更喜欢异常?这与“快速失败”的重要原则相矛盾。编译错误比异常安全得多。我相信我们需要编写一个故障安全代码。故障安全代码使用的是编译错误,而不是异常。在编译过程中,而不是在运行时,您应该真正解决或让库的用户解决尽可能多的问题。没有办法避免编译错误,您应该在编程时获得这些错误,因为任何人都可能在编写时出错。但编译错误比执行时间/逻辑错误更容易发现和修复。不管怎样,如果不先修复编译错误,就无法继续开发任何东西。我发现检测函数/运算符是否存在/可调用的唯一合法原因是,如果不存在,则提供替代操作,或者在编译时以任何方式做出决定。在运行时延迟任何事情都是胡说八道的。@Testie虽然答案100%正确,但我真的建议您重新考虑您的方法,不要偏爱异常而不是编译错误。@amit我读过这方面的内容,但任务要求我们使用异常。谢谢你的通知。@Testie:这可能取决于应用程序。有时,您无法在编译时知道某些东西是否会/应该工作。但我同意,一般来说,您应该尽可能多地压缩编译时间。为什么*OutputStream*0而不仅仅是std::declval?@iavr旧习惯-修复