重载解析和运算符<<的问题用于模板化类型-第2部分 [英] problems with overload resolution and operator<< for templated types - part 2

查看:81
本文介绍了重载解析和运算符<<的问题用于模板化类型-第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>
typename enable_if< ! has_insertion_operator<T>::value, string>::type stringify(const T&) {
    return "{?}";
}

// ======= OVERLOADS PROVIDED BY THE USER =======

template<typename T, typename T2>
struct myType { T data; T2 op; };

template<typename T, typename T2>
ostream& operator<<(ostream& s, const myType<T, T2>&) { s << "myType"; return s; }

template<typename T>
ostream& operator<<(ostream& s, const vector<T>&) { s << "vector<T>"; return s; }

template<typename T, typename A>
ostream& operator<<(ostream& s, const vector<T, A>&) { s << "vector<T, A>"; return s; }

int main() {
    myType<int, float> a;   cout << stringify(a) << endl; // prints "myType"
                            cout << stringify(6) << endl; // prints "6"
    vector<int> v(5);       cout << stringify(v) << endl; // prints "{?}"

    return 0;
}

为什么模板myType<>被字符串化但模板化的vector<>类型没有字符串化?

Why does the template myType<> get stringified but the templated vector<> type doesn't?

对于vector<>类型,我得到默认的{?}字符串化,但我显然希望调用底部的重载之一-与myType<>

For the vector<> type I get the default {?} stringification but I clearly want one of the overloads at the bottom to be called - just like with myType<>

这里的实际问题是为什么has_insertion_operator<vector<int>>是假的?

The actual question here is Why is has_insertion_operator<vector<int>> false?

我在C ++ 98中也需要这个

I also need this in C++98

并且operator<<重载应在stringify()之后提供-与myType<>

And the operator<< overloads should be supplied after stringify() - like with myType<>

推荐答案

我认为问题出在查找上,我将提供我的理解.

I think the problem is with the lookup and I will provide my understanding.

当您在has...结构参数中调用operator<<时,依赖查找就会开始,并且由于myType与重载的operator<<位于相同的命名空间中,因此它会建立,并且您会获得正确的字符串.但是,当您尝试输出vector时,它会尝试使用相同的依赖于参数的查找规则来搜索重载的operator<<,但由于std命名空间中没有重载的运算符,因此无法执行此操作.因此,它会退回到不合格的搜索,该搜索从进行调用的名称空间开始,因此会找到您的存根operator<<

When you call the operator<< in your has... struct argument dependent lookup kicks in and since myType lives in the same namespace that the overloaded operator<< it gets founded and you get a correct string. But when you try to output a vector it tries to search for the overloaded operator<< by the same argument-dependent lookup rules and fails to do it since there are no overloaded operators in std namespace. So it falls back to the unqualified search which starts from the namespace where the call is made, hence it finds your stub operator<<

因此,要解决此问题,您可能已将operator<<重载放置到std名称空间(标准禁止)或删除您的名称空间-会产生相同的效果.

So in order to fix it you might have placed operator<< overloads to the std namespace(which is forbidden by the Standard) or remove your namespace — it will give the same effect.

不过,您不必将所有内容都移出私有名称空间.在全局名称空间中执行以下操作就足够了:

You don't have to put everything out of the private namespace, though. It is enough to do something like this in the global namespace:

typedef char no;
typedef char yes[2];
template<typename T>
no operator<<(ostream const&, T const&);

或者,如果可能的话,最好要求库用户将其重载放入其类所在的相同名称空间中.但是,它不适用于std成员.

Or, if it is possible, it is better to require the library users to put their overloads into the same namespaces where their classes live. It will not work with std members, though.

这篇关于重载解析和运算符&lt;&lt;的问题用于模板化类型-第2部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆