特定の型に 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<<
明らかな応答を回避するために、テンプレート化された関数を、使用されていたさまざまな型の特定のバージョンに置き換えてみましたが、役に立ちませんでした。また、2 つの型の const-ness と l-value/r-value 指定子のさまざまな組み合わせを試しました (さまざまな調整operator<<
により、r-value ostream を使用したオーバーロードを指すコンパイラ メッセージが表示されます)。また、せいぜい と同じ結果が得られる独自の特性を実装しようとしました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);
}