找不到C++模板运算符匹配

tly*_*tly 7 c++ templates iterable operator-overloading c++11

我正在尝试创建一个operator<<for std::ostream和任何Iterable类型.

这是代码:

template <class T,template<class> class Iterable> inline std::ostream& operator<<(std::ostream& s,const Iterable<T>& iter){
    s << "[ ";
    bool first=false;
    for(T& e : iter){
        if(first){
            first=false;
            s << e;
        }else{
            s << ", " << e;
        }
    }
    s << " ]";
    return s;
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,找不到我的运算符作为a的匹配项,vector<uint>并且编译器尝试匹配operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x).

知道我怎么能改变过载被识别?

Bar*_*rry 5

您的问题的直接解决方案是这vector两种类型的模板,而不是一种,因此您需要编写:

template <typename... T, template <typename... > class Iterable>
inline std::ostream& operator<<(std::ostream& os, const Iterable<T...>& iter)
{
    s << "[ ";
    bool first = true; // not false
    for (const auto& e : iter) {
        // rest as before
    }
    return s << " ]";
}
Run Code Online (Sandbox Code Playgroud)

这有效,但有点不令人满意 - 因为模板的某些东西不可迭代,而某些不是模板的东西则可迭代。此外,我们实际上不需要IterableT在我们的解决方案中。那么我们写一些接受任何 Range 的东西怎么样——我们将 Range 定义为具有begin()and 的东西end()

template <typename Range>
auto operator<<(std::ostream& s, const Range& range) 
-> decltype(void(range.begin()), void(range.end()), s)
{
    // as above, except our container is now named 'range'
}
Run Code Online (Sandbox Code Playgroud)

如果这笼统了,那么你可以这样做:

template <typename T> struct is_range : std::false_type;
template <typename T, typename A>
struct is_range<std::vector<T,A>> : std::true_type;
// etc.

template <typename Range>
typename std::enable_if<
    is_range<Range>::value,
    std::ostream&
>::type
operator<<(std::ostream& s, const Range& range)    
Run Code Online (Sandbox Code Playgroud)

  • 你可以只写一个 `typename std::enable_if&lt;is_container&lt;CONTAINER&gt;::value, std::ostream&amp;&gt;::type` 并为 `is_container` 提供一个你想要的类型特征。 (2认同)