如何检测类型是否具有运算符<<重载?

How can I detect if a type has an operator << overload?

本文关键字:lt 运算符 重载 是否 何检测 检测 类型      更新时间:2023-10-16

我想编写一个通用的打印模板,所以这个问题的更具体的措辞是:我如何确定某些operator<<方法是否重载了类型?

这可以使用boost来完成。TypeTraits,特别是has_left_shift。一个例子:

#include <iostream>
#include "boost/type_traits.hpp"
struct foo
{
    int i;
};
struct bar
{
    int j;
};
std::ostream& operator<<(std::ostream& os, const foo& f)
{
    return os << f.i;
}
int main()
{
    // Prints out 1 == true
    std::cout << boost::has_left_shift<std::ostream&, foo&, std::ostream&>::value << 'n';
    // Prints out 0 == false
    std::cout << boost::has_left_shift<std::ostream&, bar&, std::ostream&>::value << 'n';
}

但是,请注意文档底部列出的已知问题。

SFINAE可以帮助您检查是否提供了某个方法。

#include <iostream>
struct Generic {};
struct Printable{};
std::ostream& operator<<(std::ostream& o, const Printable& t) {
    return o;
}
// SFINAE test
typedef char one;
typedef struct { char a[2]; } two;
template <typename T> static one printable_test(std::ostream&o, decltype (o << T{}, 0) ) ;
template <typename T> static two printable_test(...);
template <typename T> bool printable_with(std::ostream& o) { 
    return sizeof(printable_test<T>(o, 0)) == sizeof(one);
}
int main() {
    std::cout << std::boolalpha << printable_with<Generic>(std::cout) << std::endl;
    std::cout << std::boolalpha << printable_with<Printable>(std::cout) << std::endl;
    return 0;
}

生活一些解释。

有两个重载的函数模板printable_test, printable_with()中调用它们的重载解析结果会告诉结果。

第一个版本以decltype (o << T{}, 0)作为第二个参数,只有在o << T{}有效的情况下才有效,即在T上提供了operator<<,然后decltype将以0(逗号表达式的最后一个表达式)作为其类型,因此该版本将最匹配调用。

否则,即未提供T上的operator<<,则采用第二版。