我对此的看法:您可以按原样使用您找到的元函数,它运行良好。让我们仍然简要讨论它为什么起作用:
sizeof
实际上并不计算表达式;它推断出它的类型并返回该类型的大小。类型大小是实现定义的,我们不能对它们做太多假设,但我们知道sizeof(char) != sizeof(char[2])
,所以我们使用这些类型进行测试。
我们使用any_t
类型在命名空间级别定义流运算符,它将接受 - 你猜对了 - 任何类型并让它返回一些东西(实际上什么类型并不重要,只要它不是ostream &
)。如果类型没有定义流运算符,这就是我们回退的。在类本身中,我们现在定义了两个函数,一个采用ostream &
,如果定义了流运算符,这将是结果,另一个采用我们为回退函数定义的返回类型。
我们现在可以sizeof(test(s << c))
再次测试哪个不会计算表达式,只确定返回类型并返回其大小。
现在我们了解了它的工作原理,剩下要做的就是将它嵌入到我们的应用程序中。有几种方法可以做到这一点;在 C++11 之前也可以使用的一种方法是使用仿函数:
template <bool, typename T>
struct to_string_functor
{
std::string operator()(T const & t) const
{
std::stringstream ss;
ss << t;
return ss.str();
}
};
template <typename T>
struct to_string_functor<false, T>
{
std::string operator()(T const &) const
{
return typeid(T).name();
}
};
template <typename T>
struct foo
{
std::string to_string() const
{
return to_string_functor<
has_insertion_operator<T>::value, T
>()(m_Value);
}
/* ... */
};
有更多方法可以做到这一点,另一种方法是enable_if
,如果 C++11 可供您使用(您可能需要部分专用函数来执行此操作);你可能想阅读这篇关于这个问题的优秀博客文章。
然而,在这种简单的情况下,我认为应该使用仿函数。