我正在尝试找到一个工作类型特征来检测给定类型是否具有用于 a 的左移运算符重载std::ostream
(例如可与std::cout
or互操作boost::lexical_cast
)。boost::has_left_shift
除了类型是 POD 或类型的 STL 容器的情况外,我已经取得了成功std::string
。我怀疑这与 STL 类型或 operator<< 函数的特化有关。使用有效的左移运算符一般识别类型的正确方法是什么std::ostream
?如果这不可行,是否有单独的方法来检测 POD 或 std::string 类型的 STL 容器上的左移运算符的过载?
下面的代码显示了我当前正在使用的代码,并演示了如何boost::has_left_shift
无法检测到重载operator<<
函数,即使它在下一行被调用。该程序在 GCC 4.5.1 或更高版本和 clang 3.1 中编译和工作。
为了规避明显的反应,我尝试将模板化operator<<
函数替换为用于各种类型的特定版本,但无济于事。我还尝试了这两种类型的 const-ness 和 l-value/r-value 说明符的各种组合(各种调整使我看到编译器消息指向operator<<
带有 r-value ostream 的重载)。我也尝试过实现我自己的 trait,它充其量给我的结果与boost::has_left_shift
.
提前感谢您提供的任何帮助。如果能详细解释为什么会发生这种行为以及解决方案的工作原理,我也将不胜感激。我正在扩展我的模板知识的极限,并且很想知道为什么这不能像我想象的那样工作。
#include <string>
#include <vector>
#include <iostream>
#include <boost/lexical_cast.hpp>
#include <boost/type_traits/has_left_shift.hpp>
using namespace std;
struct Point {
int x;
int y;
Point(int x, int y) : x(x), y(y) {}
string getStr() const { return "("+boost::lexical_cast<string>(x)+","+boost::lexical_cast<string>(y)+")"; }
};
ostream& operator<<(ostream& stream, const Point& p)
{
stream << p.getStr();
return stream;
}
template <typename T>
ostream& operator<<(ostream& stream, const std::vector<T>& v)
{
stream << "[";
for(auto it = v.begin(); it != v.end(); ++it)
{
if(it != v.begin())
stream << ", ";
stream << *it;
}
stream << "]";
return stream;
}
template <typename T>
void print(const string& name, T& t)
{
cout << name << " has left shift = " << boost::has_left_shift<ostream , T>::value << endl;
cout << "t = " << t << endl << endl;
}
int main()
{
cout << boolalpha;
int i = 1;
print("int", i);
string s = "asdf";
print("std::string", s);
Point p(2,3);
print("Point", p);
vector<int> vi({1, 2, 3});
print("std::vector<int>", vi);
vector<string> vs({"x", "y", "z"});
print("std::vector<std::string>", vs);
vector<Point> vp({Point(1,2), Point(3,4), Point(5,6)});
print("std::vector<Point>", vp);
}