模板类型的重载决议和运算符<<的问题
problems with overload resolution and operator<< for templated types
我正在编写一个库,它应该将对象字符串化。
我选择支持operator<<(ostream&...
。
另一件事是我的库应该提供 {?}
形式中没有 operator<<(ostream&...
的类型的默认字符串化。
问题出在像 vector<>
这样的模板化类型上 - 我不希望用户为 vector<int>
和 vector<float>
编写 2 个重载 - 但我无法让它工作。
代码如下:
#include <string>
#include <type_traits>
#include <sstream>
#include <vector>
#include <iostream>
using namespace std;
namespace has_insertion_operator_impl {
typedef char no;
typedef char yes[2];
struct any_t {
template <typename T>
any_t(T const&);
};
no operator<<(ostream const&, any_t const&);
yes& test(ostream&);
no test(no);
template <typename T>
struct has_insertion_operator {
static ostream& s;
static T const& t;
static bool const value = sizeof(test(s << t)) == sizeof(yes);
};
}
template <typename T>
struct has_insertion_operator : has_insertion_operator_impl::has_insertion_operator<T> {};
template <class T>
typename enable_if<has_insertion_operator<T>::value, string>::type stringify(const T& in) {
stringstream stream;
stream << in;
return stream.str();
}
template <class T> // note the negation here compared to the one above
typename enable_if< ! has_insertion_operator<T>::value, string>::type stringify(const T&) {
return "{?}";
}
// USER CODE:
struct myType {};
ostream& operator<<(ostream& s, const myType&) { s << "myType"; return s; }
template<typename T>
ostream& operator<<(ostream& s, const vector<T>&) { s << "vector<T>"; return s; }
int main() {
myType a; cout << stringify(a) << endl; // prints "myType"
cout << stringify(6) << endl; // prints "6"
vector<int> v(5); cout << stringify(v) << endl; // prints "{?}" instead of "vector<T>"
return 0;
}
myType
和整数都被字符串化但是对于 vector<int>
我得到默认的 {?}
.
我需要这方面的帮助 - 这对我来说是个阻碍。我需要用户提供的 operator<<(ostream&...
重载来开箱即用,无需修改 - 所有这些都在 C++98 中。
要匹配向量,您需要为 stringize
函数提供更好的候选项
对于 C++11,这将是:
template <template <typename...> class V, typename... Args>
typename enable_if< !has_insertion_operator<V<Args...>>::value, string>::type stringify(const V<Args...>&) {
return "template {?}";
}
// also add enable_if for yes with code identical to the one in template<typename T>
由于您需要 C++98,恐怕您需要为 1 到 N(比如 5 或 10)个参数提供大量模板重载。像这样。
template <template <typename> class V, typename T0>
...
template <template <typename, typename> class V, typename T0, typename T1>
...
/// etc
例如 vector
在你的例子中有 2 个模板参数,并且将匹配第二对 yes/no
函数
原来我所要做的就是通过插入运算符特性的实现删除名称空间,这样回退 operator<<(ostream&...
最终会出现在全局范围内 - 解释 。
我正在编写一个库,它应该将对象字符串化。
我选择支持operator<<(ostream&...
。
另一件事是我的库应该提供 {?}
形式中没有 operator<<(ostream&...
的类型的默认字符串化。
问题出在像 vector<>
这样的模板化类型上 - 我不希望用户为 vector<int>
和 vector<float>
编写 2 个重载 - 但我无法让它工作。
代码如下:
#include <string>
#include <type_traits>
#include <sstream>
#include <vector>
#include <iostream>
using namespace std;
namespace has_insertion_operator_impl {
typedef char no;
typedef char yes[2];
struct any_t {
template <typename T>
any_t(T const&);
};
no operator<<(ostream const&, any_t const&);
yes& test(ostream&);
no test(no);
template <typename T>
struct has_insertion_operator {
static ostream& s;
static T const& t;
static bool const value = sizeof(test(s << t)) == sizeof(yes);
};
}
template <typename T>
struct has_insertion_operator : has_insertion_operator_impl::has_insertion_operator<T> {};
template <class T>
typename enable_if<has_insertion_operator<T>::value, string>::type stringify(const T& in) {
stringstream stream;
stream << in;
return stream.str();
}
template <class T> // note the negation here compared to the one above
typename enable_if< ! has_insertion_operator<T>::value, string>::type stringify(const T&) {
return "{?}";
}
// USER CODE:
struct myType {};
ostream& operator<<(ostream& s, const myType&) { s << "myType"; return s; }
template<typename T>
ostream& operator<<(ostream& s, const vector<T>&) { s << "vector<T>"; return s; }
int main() {
myType a; cout << stringify(a) << endl; // prints "myType"
cout << stringify(6) << endl; // prints "6"
vector<int> v(5); cout << stringify(v) << endl; // prints "{?}" instead of "vector<T>"
return 0;
}
myType
和整数都被字符串化但是对于 vector<int>
我得到默认的 {?}
.
我需要这方面的帮助 - 这对我来说是个阻碍。我需要用户提供的 operator<<(ostream&...
重载来开箱即用,无需修改 - 所有这些都在 C++98 中。
要匹配向量,您需要为 stringize
函数提供更好的候选项
对于 C++11,这将是:
template <template <typename...> class V, typename... Args>
typename enable_if< !has_insertion_operator<V<Args...>>::value, string>::type stringify(const V<Args...>&) {
return "template {?}";
}
// also add enable_if for yes with code identical to the one in template<typename T>
由于您需要 C++98,恐怕您需要为 1 到 N(比如 5 或 10)个参数提供大量模板重载。像这样。
template <template <typename> class V, typename T0>
...
template <template <typename, typename> class V, typename T0, typename T1>
...
/// etc
例如 vector
在你的例子中有 2 个模板参数,并且将匹配第二对 yes/no
函数
原来我所要做的就是通过插入运算符特性的实现删除名称空间,这样回退 operator<<(ostream&...
最终会出现在全局范围内 - 解释