重载分辨率和运算符的问题<<对于模板类型

时间:2016-05-09 16:58:05

标签: c++ templates operator-overloading overload-resolution

我正在编写一个库,它应该对对象进行字符串化。

我已选择支持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中的所有这些。

2 个答案:

答案 0 :(得分:1)

要匹配您需要的向量,以便为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)args提供一些模板重载。像这样。

template <template <typename> class V, typename T0>
...
template <template <typename, typename> class V, typename T0, typename T1>
...
/// etc

例如,您的案例中的vector有2个模板参数,并且会匹配第二对yes/no函数

答案 1 :(得分:0)

事实证明,我所要做的就是使用插入运算符trait的实现来删除命名空间,以便回退operator<<(ostream&...在全局范围内结束 - 解释here