我正在编写一个模板类,我需要一个方法将元素类打印到stdout
。但是我在编写它时遇到了问题 - 如果我的元素类中没有定义或重载cout <<
或operator const char*()
会怎么样?
有没有办法找到它可能会抛出异常而不会出现编译错误?
答案 0 :(得分:1)
如果操作符未重载,则程序无法编译。这是编译时错误,在运行时之前无法延迟。
一种方法是不使用运算符,而是使用函数指针。如果不支持该操作,则可以将函数指针设置为0,您可以在运行时检测该函数。
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和<functional>
。对于C ++ 03,您必须使用“普通”函数指针。
答案 1 :(得分:1)
您可以使用某些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)